SlideShare uma empresa Scribd logo
Better Faster
Stronger Dagger
Rafael Toledo
@_rafaeltoledo
Android Developer @ Concrete Solutions
www.rafaeltoledo.net
O que é Injeção de
Dependência?
@_rafaeltoledo
“Injeção de Dependência (ou Dependency
Injection, em inglês) é um padrão de
desenvolvimento de programas de
computadores utilizado quando é necessário
manter baixo o nível de acoplamento entre
diferentes módulos de um sistema. (...)”
@_rafaeltoledo
“Nesta solução as dependências entre os
módulos não são definidas
programaticamente, mas sim pela
configuração de uma infraestrutura de
software (container) que é responsável por
"injetar" em cada componente suas
dependências declaradas. A Injeção de
dependência se relaciona com o padrão
Inversão de controle mas não pode ser
considerada um sinônimo deste.”
Wikipedia, 2015
@_rafaeltoledo
?????????
@_rafaeltoledo
Diz respeito a separação de onde os
objetos são criados e onde são utilizados
@_rafaeltoledo
Em vez de criar, você pede
@_rafaeltoledo
class UserController {
void doLogic() {
try {
User user = RetrofitApi.getInstance().getUser(1);
new UserDaoImpl().save(user);
Logger.getForClass(UserController.class).log("Success");
} catch (IOException e) {
Logger.getForClass(UserController.class).logException(e);
}
}
}
@_rafaeltoledo
class UserController {
UserDaoImpl dao;
Logger logger;
UserApi api;
void doLogic() {
try {
api = RetrofitApi.getInstance();
User user = api.getUser(1);
dao = new UserDaoImpl();
dao.save(user);
logger = Logger.getForClass(UserController.class);
logger.log("Success");
} catch (IOException e) {
logger = Logger.getForClass(UserController.class);
logger.logException(e);
}
}
} @_rafaeltoledo
class UserController {
UserDao dao; // Interface!
Logger logger;
Api api;
void doLogic() {
try {
if (api == null) api = RetrofitApi.getInstance();
User user = api.getUser(1);
if (dao == null) dao = new UserDaoImpl();
dao.save(user);
if (logger == null) logger = Logger.getForClass(UserController.class);
logger.log("Success");
} catch (IOException e) {
if (logger == null) logger = Logger.getForClass(UserController.class);
logger.logException(e);
}
}
} @_rafaeltoledo
class UserController {
UserDao dao = new UserDaoImpl();
Logger logger = Logger.getForClass(UserController.class);
Api api = RetrofitApi.getInstance();
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) {
logger.logException(e);
}
}
}
@_rafaeltoledo
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
} @_rafaeltoledo
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
} @_rafaeltoledo
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
} @_rafaeltoledo
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
} @_rafaeltoledo
UserDao
UserController
@_rafaeltoledo
UserDao
UserController
SessionManager
@_rafaeltoledo
UserDao
UserController
SessionManager
SignInController
@_rafaeltoledo
UserDao
UserController
SessionManager
SignInController
CookieJob
JobManager
JobController
PermissionChecker
ReminderJob
RoleController
CandyShopper
FruitJuicerJob
UnknownController
@_rafaeltoledo
UserDao
UserController
SessionManager
SignInController
CookieJob
JobManager
JobController
PermissionChecker
ReminderJob
RoleController
CandyShopper
FruitJuicerJob
UnknownController
EM
TODO
LUGAR!
@_rafaeltoledo
class UserDaoImpl implements UserDao {
public UserDaoImpl() {
//...
}
}
@_rafaeltoledo
class UserDaoImpl implements UserDao {
public UserDaoImpl(Context context) {
//...
}
}
@_rafaeltoledo
@_rafaeltoledo
Alteração em todas as classes!
@_rafaeltoledo
Alteração em todas as classes!
Muito retrabalho!
@_rafaeltoledo
Alteração em todas as classes!
Muito retrabalho!
@_rafaeltoledo
Alteração em todas as classes!
Muito retrabalho!
@_rafaeltoledo
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
} @_rafaeltoledo
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController() {
dao = new UserDaoImpl();
api = RetrofitApi.getInstance();
logger = Logger.getForClass(UserController.class);
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
} @_rafaeltoledo
class UserController {
UserDao dao;
Logger logger;
Api api;
public UserController(UserDao dao, Api api, Logger logger) {
this.dao = dao;
this.api = api;
this.logger = logger;
}
void doLogic() {
try {
User user = api.getUser(1);
dao.save(user);
logger.log("Success");
} catch (IOException e) { logger.logException(e); }
}
} @_rafaeltoledo
DI: Separação do uso e criação de objetos
@_rafaeltoledo
DI: Separação do uso e criação de objetos
não há a necessidade de bibliotecas
ou frameworks!
@_rafaeltoledo
Desvantagem: muito boilerplate
@_rafaeltoledo
Spring, Guice, Dagger 1 & cia
#oldbutgold
@_rafaeltoledo
Spring, Guice, Dagger 1 & cia
#oldbutnot
@_rafaeltoledo
Dagger 2
@_rafaeltoledo
Dagger 2?
@_rafaeltoledo
Dagger 2
● Fork do Dagger, da Square, feito pela
Google
● Elimina todo o uso de reflections
● Construída sobre as anotações javax.
inject da especificação JSR-330
@_rafaeltoledo
Dagger 2
● Validação de todo o grafo de dependências
em tempo de compilação
● Menos flexível, se comparado ao Dagger 1 -
ex.: não possui module overriding
● Proguard configuration-free
@_rafaeltoledo
Dagger 2
● API enxuta!
● Código gerado é debugger-friendly
● Muito performático
● google.github.io/dagger
@_rafaeltoledo
public @interface Component {
Class<?>[] modules() default {};
Class<?>[] dependencies() default {};
}
public @interface Subcomponent {
Class<?>[] includes() default {};
}
public @interface Module {
Class<?>[] includes() default {};
}
public @interface Provides {
}
public @interface MapKey {
boolean unwrapValue() default true;
}
public interface Lazy<T> {
T get();
}
@_rafaeltoledo
// JSR-330
public @interface Inject {
}
public @interface Scope {
}
public @interface Qualifier {
}
@_rafaeltoledo
Como integro no meu projeto?
@_rafaeltoledo
// build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
}
}
allprojects {
repositories {
jcenter()
}
}
@_rafaeltoledo
// build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
}
}
allprojects {
repositories {
jcenter()
}
}
@_rafaeltoledo
// build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
allprojects {
repositories {
jcenter()
}
}
@_rafaeltoledo
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
applicationId 'net.rafaeltoledo.tdc2015'
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName '1.0'
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.0.1'
}
@_rafaeltoledo
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
applicationId 'net.rafaeltoledo.tdc2015'
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName '1.0'
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.google.dagger:dagger:2.0.1'
apt 'com.google.dagger:dagger-compiler:2.0.1'
provided 'javax.annotation:javax.annotation-api:1.2'
}
@_rafaeltoledo
apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
applicationId 'net.rafaeltoledo.tdc2015'
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName '1.0'
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.google.dagger:dagger:2.0.1'
apt 'com.google.dagger:dagger-compiler:2.0.1'
provided 'javax.annotation:javax.annotation-api:1.2' // JSR-330
}
@_rafaeltoledo
E pronto!
@_rafaeltoledo
Vamos começar?
@_rafaeltoledo
@Inject
@Component @Module
@Provides
Dagger 2
@_rafaeltoledo
@Inject
● Parte da JSR-330
● Marca quais dependências devem ser
fornecidas pelo Dagger
● Pode aparecer de 3 formas no código
@_rafaeltoledo
public class TdcActivityPresenter {
private TdcActivity activity;
private TdcDataStore dataStore;
@Inject
public TdcActivityPresenter(TdcActivity activity,
TdcDataStore dataStore) {
this.activity = activity;
this.dataStore = dataStore;
}
}
1. No Construtor
@_rafaeltoledo
1. No Construtor
● Todas as dependências vem do grafo de
dependências do Dagger
● Anotar uma classe dessa forma faz com que
ela também faça parte do grafo de
dependências (podendo ser injetada em
outras classes)
@_rafaeltoledo
1. No Construtor
● Limitação: não podemos anotar mais que
um construtor com a anotação @Inject
@_rafaeltoledo
public class TdcActivity extends AppCompatActivity {
@Inject TdcActivityPresenter presenter;
@Inject SharedPreferences preferences;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
getComponent().inject(this);
}
}
2. Nos Atributos da Classe
@_rafaeltoledo
2. Nos Atributos da Classe
● A injeção nesse caso deve ser manual, caso
contrários os atributos serão todos nulos
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
getComponent().inject(this);
}
● Limitação: os atributos não podem ser
privados!
@_rafaeltoledo
public class TdcActivityPresenter {
private TdcActivity activity;
@Inject
public TdcActivityPresenter(TdcActivity activity) {
this.activity = activity;
}
@Inject
public void enableAnalytics(AnalyticsManager analytics) {
analytics.track(this);
}
}
3. Em métodos públicos
@_rafaeltoledo
3. Em métodos públicos
● Utilizado em conjunto com a anotação no
construtor da classe
● Para casos onde o objeto injetado
necessitamos da instância da própria classe
na dependência fornecida
@Inject
public void enableAnalytics(AnalyticsManager analytics) {
analytics.track(this);
}
@_rafaeltoledo
3. Em métodos públicos
● O método anotado é chamado
automaticamente logo após o construtor
@_rafaeltoledo
@Module
● Parte da API do Dagger
● Utilizada para identificar classes que
fornecem dependências
@_rafaeltoledo
@Module
public class DataModule {
@Provides @Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
return okHttpClient;
}
@Provides @Singleton
public RestAdapter provideRestAdapter(OkHttpClient client) {
return new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setEndpoint("https://api.github.com")
.build();
}
} @_rafaeltoledo
@Module
public class DataModule {
@Provides @Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
return okHttpClient;
}
@Provides @Singleton
public RestAdapter provideRestAdapter(OkHttpClient client) {
return new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setEndpoint("https://api.github.com")
.build();
}
} @_rafaeltoledo
@Provides
● Utilizada nas classes anotadas como
@Module para identificar quais métodos
retornam dependências
@_rafaeltoledo
@Module
public class DataModule {
@Provides @Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
return okHttpClient;
}
@Provides @Singleton
public RestAdapter provideRestAdapter(OkHttpClient client) {
return new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setEndpoint("https://api.github.com")
.build();
}
} @_rafaeltoledo
@Module
public class DataModule {
@Provides @Singleton
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS);
okHttpClient.setReadTimeout(10, TimeUnit.SECONDS);
okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
return okHttpClient;
}
@Provides @Singleton
public RestAdapter provideRestAdapter(OkHttpClient client) {
return new RestAdapter.Builder()
.setClient(new OkClient(okHttpClient))
.setEndpoint("https://api.github.com")
.build();
}
} @_rafaeltoledo
@Component
● É a anotação que liga os @Modules aos
@Injects
● É colocada em uma interface
● Define quais módulos possui, quem será
injetado
@_rafaeltoledo
@Component
● Precisa especificar obrigatoriamente seu
escopo (ciclo de vida de suas dependências)
● Pode publicar dependências
● Pode possuir outros componentes
@_rafaeltoledo
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
@_rafaeltoledo
@Singleton // Escopo
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
@_rafaeltoledo
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
@_rafaeltoledo
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity); // Caso queira encadear
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
@_rafaeltoledo
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager(); // Dependências visíveis
} // para outros componentes*
@_rafaeltoledo
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
@_rafaeltoledo
@ActivityScope // Escopo personalizado
@Component(
modules = TdcActivityModule.class,
dependencies = TdcComponent.class
)
public interface TdcActivityComponent {
TdcActivity inject(TdcActivity activity);
TdcActivityPresenter presenter();
}
@_rafaeltoledo
@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerMainComponent implements MainComponent {
private Provider<ApiService> provideApiServiceProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerMainComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static MainComponent create() {
return builder().build();
}
private void initialize(final Builder builder) {
this.provideApiServiceProvider =
ScopedProvider.create(MainModule_ProvideApiServiceFactory.create(builder.mainModule));
this.mainActivityMembersInjector = MainActivity_MembersInjector.create(
(MembersInjector) MembersInjectors.noOp(), provideApiServiceProvider);
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
}
@_rafaeltoledo
public class TdcApp extends Application {
TdcAppComponent component;
@Override
public void onCreate() {
component = DaggerTdcAppComponent.create();
component = DaggerTdcAppComponent.builder()
.dataModule(new DataModule(this)) // Módulo com construtor
.build(); // parametrizado
}
}
Instanciando um Componente
@_rafaeltoledo
Dagger 2
Escopos dinâmicos
@_rafaeltoledo
Escopo = ciclo de vida do grafo de
dependências (componente)
@_rafaeltoledo
@Singleton
@Component(
modules = {
DataModule.class,
UiModule.class
}
)
public interface TdcAppComponent {
void inject(TdcApplication app);
MainActivity inject(MainActivity activity);
Application getApplication();
AnalyticsManager getAnalyticsManager();
}
@_rafaeltoledo
@ActivityScope // Escopo personalizado
@Component(
modules = TdcActivityModule.class,
dependencies = TdcComponent.class
)
public interface TdcActivityComponent {
TdcActivity inject(TdcActivity activity);
TdcActivityPresenter presenter();
}
@_rafaeltoledo
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface UserScope {
}
Definição de um escopo
@_rafaeltoledo
Exemplo de uso
Miroslaw Stanek frogermcs.github.io
@_rafaeltoledo
@Singleton
@Component(modules = DataModule.class)
public interface TdcAppComponent {
UserComponent plus(UserModule module);
// não é necessário expor as dependências
}
Implementação
@_rafaeltoledo
@UserScope
@Subcomponent(modules = UserModule.class)
public interface UserComponent {
UserActivityComponent plus(UserActivityModule module);
}
Implementação
@_rafaeltoledo
public class TdcApp extends Application {
TdcAppComponent component;
UserComponent userComponent;
public UserComponent createUserComponent(User user) {
userComponent = component.plus(new UserModule(user));
return userComponent;
}
public void releaseUserComponent() {
userComponent = null;
}
...
}
Implementação
@_rafaeltoledo
Dagger 2
Outras coisas legais!
@_rafaeltoledo
@Inject
Lazy<SharedPreferences> prefs;
void salvar() {
prefs.get().edit().putString("status", "ok!").apply();
}
Dependências “Preguiçosas”
@_rafaeltoledo
// No módulo
@Provides @Singleton
@ApiUrl String provideApiUrl(Context context) {
return context.getString(R.string.api_url);
}
@Provides @Singleton
@AccessToken String provideRestAdapter(SharedPreferences prefs) {
return prefs.getString("token", null);
}
// Na classe a ser injetada
@Inject @AccessToken
String accessToken;
Qualificadores
@_rafaeltoledo
// Declarando sua anotação
@MapKey(unwrapValue = true)
@interface GroupKey {
String value();
}
@MapKey
@_rafaeltoledo
// Fornecendo dependências no módulo
@Provides(type = Type.MAP)
@GroupKey("um")
String provideFirstValue() {
return "primeiro valor";
}
@Provides(type = Type.MAP)
@GroupKey("dois")
String provideSecondValue() {
return "segundo valor";
}
@MapKey
@_rafaeltoledo
// Uso
@Inject
Map<String, String> map; // {um=primeiro valor, dois=segundo valor}
Por enquanto, só aceita Map e Set, e valores
do tipo String e Enumeradores
@MapKey
@_rafaeltoledo
Ok! Tudo muito bonito mas...
@_rafaeltoledo
O que eu ganho de fato com tudo isso?
@_rafaeltoledo
Grandes benefícios
● Código mais limpo e organizado
● Melhorias no gerenciamento de objetos
(melhor controle de singletons)
● Código mais fácil de TESTAR
@_rafaeltoledo
Dagger 2 e Testes
● Programar orientado a interfaces - mocks
● Sobrescrita de Componentes e Módulos
@_rafaeltoledo
Dagger 2 e Testes
@Module
public class TestMainModule {
@Provides // Poderíamos fazer com o Retrofit Mock!
public ApiService provideApiService() {
return new ApiService() {
@Override
public List<Repo> listRepos() {
return Arrays.asList(
new Repo("my-test-repo"),
new Repo("another-test-repo")
);
}
};
}
} @_rafaeltoledo
Dagger 2 e Testes
@Component(modules = DebugMainModule.class)
public interface TestMainComponent extends MainComponent {
}
@_rafaeltoledo
Dagger 2 e Espresso 2
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {
// ...
@Before
public void setUp() {
Instrumentation instrumentation =
InstrumentationRegistry.getInstrumentation();
MainApplication app = (MainApplication)
instrumentation.getTargetContext().getApplicationContext();
app.setComponent(DaggerDebugMainComponent.create());
rule.launchActivity(new Intent());
}
}
@_rafaeltoledo
Dagger 2 e Robolectric 3
@RunWith(RobolectricGradleTestRunner.class)
@Config(sdk = 21, constants = BuildConfig.class)
public class MainActivityTest {
// ...
@Before
public void setUp() {
MainComponent component = DaggerDebugMainComponent.create();
MainApplication app =
((MainApplication) RuntimeEnvironment.application)
.setComponent(component);
}
}
@_rafaeltoledo
Dagger 2
github.com/rafaeltoledo/dagger2-tdc2015
@_rafaeltoledo
Para saber mais
● Site oficial - google.github.io/dagger
● Dagger 2 - A New Type of Dependency
Injection (Gregory Kick) - vai.la/fdwt
● The Future of Dependency Injection with
Dagger 2 (Jake Wharton) - vai.la/fdwy
● froger_mcs Dev Blog - frogermcs.github.io
OBRIGADO!
rafaeltoledo.net
@_rafaeltoledo
Desenv. Android @ Concrete Solutions
concretesolutions.com.br/carreira

Mais conteúdo relacionado

Mais procurados

JUnit 5 vs JUnit 4
JUnit 5 vs JUnit 4JUnit 5 vs JUnit 4
JUnit 5 vs JUnit 4
Ismael
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
tdc-globalcode
 
Liferay e Modularização com Arquitetura OSGi
Liferay e Modularização com Arquitetura OSGiLiferay e Modularização com Arquitetura OSGi
Liferay e Modularização com Arquitetura OSGi
André Ricardo Barreto de Oliveira
 
Desenvolvimento Dirigido por Testes com Junit
Desenvolvimento Dirigido por Testes com JunitDesenvolvimento Dirigido por Testes com Junit
Desenvolvimento Dirigido por Testes com Junit
Adolfo Neto
 
Seminário sd android_exemplos
Seminário sd android_exemplosSeminário sd android_exemplos
Seminário sd android_exemplos
Calvin Rodrigues
 
Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e applets
Denis L Presciliano
 
Fazendo Injeção de dependência com Unity 1.2
Fazendo Injeção de dependência com Unity 1.2Fazendo Injeção de dependência com Unity 1.2
Fazendo Injeção de dependência com Unity 1.2
Giovanni Bassi
 
De a máxima cobertura nos seus testes de API
De a máxima cobertura nos seus testes de APIDe a máxima cobertura nos seus testes de API
De a máxima cobertura nos seus testes de API
Elias Nogueira
 
JUnit
JUnitJUnit
Introdução a testes unitários com jUnit
Introdução a testes unitários com jUnitIntrodução a testes unitários com jUnit
Introdução a testes unitários com jUnit
Leonardo Soares
 
Testes de Unidade com JUnit
Testes de Unidade com JUnitTestes de Unidade com JUnit
Testes de Unidade com JUnit
elliando dias
 
Aula JPA
Aula JPAAula JPA
Aula JPA
Marco Reis
 
Vraptor
VraptorVraptor
Vraptor
clauvane1708
 
Robotium_Sikuli
Robotium_SikuliRobotium_Sikuli
Robotium_Sikuli
Lucas Cortazzo
 
Introdução ao JavaFX
Introdução ao JavaFXIntrodução ao JavaFX
Introdução ao JavaFX
Nécio de Lima Veras
 
Maven
MavenMaven
Conhecendo o Spring
Conhecendo o SpringConhecendo o Spring
Conhecendo o Spring
Maurício Linhares
 
Palestra Testes Unidade Com JUnit
Palestra Testes Unidade Com JUnitPalestra Testes Unidade Com JUnit
Palestra Testes Unidade Com JUnit
Robinson Castilho
 
JavaEE 7, na era do cloud computing
JavaEE 7, na era do cloud computingJavaEE 7, na era do cloud computing
JavaEE 7, na era do cloud computing
Eder Magalhães
 

Mais procurados (19)

JUnit 5 vs JUnit 4
JUnit 5 vs JUnit 4JUnit 5 vs JUnit 4
JUnit 5 vs JUnit 4
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
Liferay e Modularização com Arquitetura OSGi
Liferay e Modularização com Arquitetura OSGiLiferay e Modularização com Arquitetura OSGi
Liferay e Modularização com Arquitetura OSGi
 
Desenvolvimento Dirigido por Testes com Junit
Desenvolvimento Dirigido por Testes com JunitDesenvolvimento Dirigido por Testes com Junit
Desenvolvimento Dirigido por Testes com Junit
 
Seminário sd android_exemplos
Seminário sd android_exemplosSeminário sd android_exemplos
Seminário sd android_exemplos
 
Como construir aplicações gráficas e applets
Como construir aplicações gráficas e appletsComo construir aplicações gráficas e applets
Como construir aplicações gráficas e applets
 
Fazendo Injeção de dependência com Unity 1.2
Fazendo Injeção de dependência com Unity 1.2Fazendo Injeção de dependência com Unity 1.2
Fazendo Injeção de dependência com Unity 1.2
 
De a máxima cobertura nos seus testes de API
De a máxima cobertura nos seus testes de APIDe a máxima cobertura nos seus testes de API
De a máxima cobertura nos seus testes de API
 
JUnit
JUnitJUnit
JUnit
 
Introdução a testes unitários com jUnit
Introdução a testes unitários com jUnitIntrodução a testes unitários com jUnit
Introdução a testes unitários com jUnit
 
Testes de Unidade com JUnit
Testes de Unidade com JUnitTestes de Unidade com JUnit
Testes de Unidade com JUnit
 
Aula JPA
Aula JPAAula JPA
Aula JPA
 
Vraptor
VraptorVraptor
Vraptor
 
Robotium_Sikuli
Robotium_SikuliRobotium_Sikuli
Robotium_Sikuli
 
Introdução ao JavaFX
Introdução ao JavaFXIntrodução ao JavaFX
Introdução ao JavaFX
 
Maven
MavenMaven
Maven
 
Conhecendo o Spring
Conhecendo o SpringConhecendo o Spring
Conhecendo o Spring
 
Palestra Testes Unidade Com JUnit
Palestra Testes Unidade Com JUnitPalestra Testes Unidade Com JUnit
Palestra Testes Unidade Com JUnit
 
JavaEE 7, na era do cloud computing
JavaEE 7, na era do cloud computingJavaEE 7, na era do cloud computing
JavaEE 7, na era do cloud computing
 

Destaque

Design a arte de materializar as decisoes de negocios
Design a arte de materializar as decisoes de negociosDesign a arte de materializar as decisoes de negocios
Design a arte de materializar as decisoes de negocios
tdc-globalcode
 
sap startup focus acelerando startus brasileiras com sap hana
sap startup focus acelerando startus brasileiras com sap hanasap startup focus acelerando startus brasileiras com sap hana
sap startup focus acelerando startus brasileiras com sap hana
tdc-globalcode
 
Por que sua próxima aplicação web deve ser em Clojure?
Por que sua próxima aplicação web deve ser em Clojure?Por que sua próxima aplicação web deve ser em Clojure?
Por que sua próxima aplicação web deve ser em Clojure?
Eduardo Aquiles Affonso Radanovitsck
 
Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o mo...
Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o mo...Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o mo...
Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o mo...
tdc-globalcode
 
O que aprendi com minha empresa
O que aprendi com minha empresaO que aprendi com minha empresa
O que aprendi com minha empresa
tdc-globalcode
 
De 0 a10000 usuarios em 3 meses
De 0 a10000 usuarios em 3 mesesDe 0 a10000 usuarios em 3 meses
De 0 a10000 usuarios em 3 meses
tdc-globalcode
 
o que e ser cio de uma startup?
o que e ser cio de uma startup?o que e ser cio de uma startup?
o que e ser cio de uma startup?
tdc-globalcode
 
como esta a arquitetura do seu app?
como esta a arquitetura do seu app?como esta a arquitetura do seu app?
como esta a arquitetura do seu app?
tdc-globalcode
 
Criando app Android utilizando Kotlin
Criando app Android utilizando KotlinCriando app Android utilizando Kotlin
Criando app Android utilizando Kotlin
Luiz Henrique Santana
 
Reconstruindo a Torre de Babel com RequireJS
Reconstruindo a Torre de Babel com RequireJSReconstruindo a Torre de Babel com RequireJS
Reconstruindo a Torre de Babel com RequireJS
tdc-globalcode
 
Repaint/Reflow/Dom/RenderTree - Renderizando uma página web
Repaint/Reflow/Dom/RenderTree - Renderizando uma página webRepaint/Reflow/Dom/RenderTree - Renderizando uma página web
Repaint/Reflow/Dom/RenderTree - Renderizando uma página web
tdc-globalcode
 
Do relogio ao carro
Do relogio ao carroDo relogio ao carro
Do relogio ao carro
tdc-globalcode
 
introdução a pretotyping fazer a coisa certa mais do que fazer certo a coisa
introdução a pretotyping  fazer a coisa certa mais do que fazer certo a coisaintrodução a pretotyping  fazer a coisa certa mais do que fazer certo a coisa
introdução a pretotyping fazer a coisa certa mais do que fazer certo a coisa
tdc-globalcode
 
Instagram: que tipo de conteúdo o público prefere?
Instagram: que tipo de conteúdo o público prefere?Instagram: que tipo de conteúdo o público prefere?
Instagram: que tipo de conteúdo o público prefere?
tdc-globalcode
 
cakephp 3.0 o bolo ainda serve muita gente
cakephp 3.0 o bolo ainda serve muita gentecakephp 3.0 o bolo ainda serve muita gente
cakephp 3.0 o bolo ainda serve muita gente
tdc-globalcode
 
Como impulsionar a sua carreira atraves das redes sociais?
Como impulsionar a sua carreira atraves das redes sociais?Como impulsionar a sua carreira atraves das redes sociais?
Como impulsionar a sua carreira atraves das redes sociais?
tdc-globalcode
 
Polo: Desenvolvendo os problemas de inconsistência de dados em projetos Rails
Polo: Desenvolvendo os problemas de inconsistência de dados em projetos RailsPolo: Desenvolvendo os problemas de inconsistência de dados em projetos Rails
Polo: Desenvolvendo os problemas de inconsistência de dados em projetos Rails
tdc-globalcode
 
A experiência da AGCO ao adotar o BDD em seus projetos: uma experiência excit...
A experiência da AGCO ao adotar o BDD em seus projetos: uma experiência excit...A experiência da AGCO ao adotar o BDD em seus projetos: uma experiência excit...
A experiência da AGCO ao adotar o BDD em seus projetos: uma experiência excit...
tdc-globalcode
 
Gere resultados com Facebook Ads
Gere resultados com Facebook AdsGere resultados com Facebook Ads
Gere resultados com Facebook Ads
tdc-globalcode
 
Gerenciando o ciclo de vida de aplicações com AWS Elastic Beanstalk
Gerenciando o ciclo de vida de aplicações com AWS Elastic BeanstalkGerenciando o ciclo de vida de aplicações com AWS Elastic Beanstalk
Gerenciando o ciclo de vida de aplicações com AWS Elastic Beanstalk
tdc-globalcode
 

Destaque (20)

Design a arte de materializar as decisoes de negocios
Design a arte de materializar as decisoes de negociosDesign a arte de materializar as decisoes de negocios
Design a arte de materializar as decisoes de negocios
 
sap startup focus acelerando startus brasileiras com sap hana
sap startup focus acelerando startus brasileiras com sap hanasap startup focus acelerando startus brasileiras com sap hana
sap startup focus acelerando startus brasileiras com sap hana
 
Por que sua próxima aplicação web deve ser em Clojure?
Por que sua próxima aplicação web deve ser em Clojure?Por que sua próxima aplicação web deve ser em Clojure?
Por que sua próxima aplicação web deve ser em Clojure?
 
Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o mo...
Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o mo...Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o mo...
Fundamentos de Akka.net para sistemas concorrentes e distribuidos usando o mo...
 
O que aprendi com minha empresa
O que aprendi com minha empresaO que aprendi com minha empresa
O que aprendi com minha empresa
 
De 0 a10000 usuarios em 3 meses
De 0 a10000 usuarios em 3 mesesDe 0 a10000 usuarios em 3 meses
De 0 a10000 usuarios em 3 meses
 
o que e ser cio de uma startup?
o que e ser cio de uma startup?o que e ser cio de uma startup?
o que e ser cio de uma startup?
 
como esta a arquitetura do seu app?
como esta a arquitetura do seu app?como esta a arquitetura do seu app?
como esta a arquitetura do seu app?
 
Criando app Android utilizando Kotlin
Criando app Android utilizando KotlinCriando app Android utilizando Kotlin
Criando app Android utilizando Kotlin
 
Reconstruindo a Torre de Babel com RequireJS
Reconstruindo a Torre de Babel com RequireJSReconstruindo a Torre de Babel com RequireJS
Reconstruindo a Torre de Babel com RequireJS
 
Repaint/Reflow/Dom/RenderTree - Renderizando uma página web
Repaint/Reflow/Dom/RenderTree - Renderizando uma página webRepaint/Reflow/Dom/RenderTree - Renderizando uma página web
Repaint/Reflow/Dom/RenderTree - Renderizando uma página web
 
Do relogio ao carro
Do relogio ao carroDo relogio ao carro
Do relogio ao carro
 
introdução a pretotyping fazer a coisa certa mais do que fazer certo a coisa
introdução a pretotyping  fazer a coisa certa mais do que fazer certo a coisaintrodução a pretotyping  fazer a coisa certa mais do que fazer certo a coisa
introdução a pretotyping fazer a coisa certa mais do que fazer certo a coisa
 
Instagram: que tipo de conteúdo o público prefere?
Instagram: que tipo de conteúdo o público prefere?Instagram: que tipo de conteúdo o público prefere?
Instagram: que tipo de conteúdo o público prefere?
 
cakephp 3.0 o bolo ainda serve muita gente
cakephp 3.0 o bolo ainda serve muita gentecakephp 3.0 o bolo ainda serve muita gente
cakephp 3.0 o bolo ainda serve muita gente
 
Como impulsionar a sua carreira atraves das redes sociais?
Como impulsionar a sua carreira atraves das redes sociais?Como impulsionar a sua carreira atraves das redes sociais?
Como impulsionar a sua carreira atraves das redes sociais?
 
Polo: Desenvolvendo os problemas de inconsistência de dados em projetos Rails
Polo: Desenvolvendo os problemas de inconsistência de dados em projetos RailsPolo: Desenvolvendo os problemas de inconsistência de dados em projetos Rails
Polo: Desenvolvendo os problemas de inconsistência de dados em projetos Rails
 
A experiência da AGCO ao adotar o BDD em seus projetos: uma experiência excit...
A experiência da AGCO ao adotar o BDD em seus projetos: uma experiência excit...A experiência da AGCO ao adotar o BDD em seus projetos: uma experiência excit...
A experiência da AGCO ao adotar o BDD em seus projetos: uma experiência excit...
 
Gere resultados com Facebook Ads
Gere resultados com Facebook AdsGere resultados com Facebook Ads
Gere resultados com Facebook Ads
 
Gerenciando o ciclo de vida de aplicações com AWS Elastic Beanstalk
Gerenciando o ciclo de vida de aplicações com AWS Elastic BeanstalkGerenciando o ciclo de vida de aplicações com AWS Elastic Beanstalk
Gerenciando o ciclo de vida de aplicações com AWS Elastic Beanstalk
 

Semelhante a better faster stronger dagger

(A10) LabMM3 - JavaScript - Subalgoritmos
(A10) LabMM3 - JavaScript - Subalgoritmos(A10) LabMM3 - JavaScript - Subalgoritmos
(A10) LabMM3 - JavaScript - Subalgoritmos
Carlos Santos
 
Programando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um FrameworkProgramando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um Framework
Pablo Dall'Oglio
 
TDC 2014 SP - E o DeltaSpike ?
TDC 2014 SP - E o DeltaSpike ?TDC 2014 SP - E o DeltaSpike ?
TDC 2014 SP - E o DeltaSpike ?
Rafael Benevides
 
Ecosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_javEcosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_jav
Julio Viegas
 
Dependency injection WTF? - PHPSC Conference 2012
Dependency injection WTF? - PHPSC Conference 2012Dependency injection WTF? - PHPSC Conference 2012
Dependency injection WTF? - PHPSC Conference 2012
Luís Cobucci
 
T10_LM3: Subalgoritmos/funções (2013-2014)
T10_LM3: Subalgoritmos/funções (2013-2014)T10_LM3: Subalgoritmos/funções (2013-2014)
T10_LM3: Subalgoritmos/funções (2013-2014)
Carlos Santos
 
Testando Rails apps com RSpec
Testando Rails apps com RSpecTestando Rails apps com RSpec
Testando Rails apps com RSpec
Nando Vieira
 
Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Introdução ao Zend Framework 2
Introdução ao Zend Framework 2
Elton Minetto
 
LabMM3 - Aula teórica 08
LabMM3 - Aula teórica 08LabMM3 - Aula teórica 08
LabMM3 - Aula teórica 08
Carlos Santos
 
Spring & Struts
Spring & StrutsSpring & Struts
Spring & Struts
eduan
 
VRaptor4
VRaptor4VRaptor4
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
tdc-globalcode
 
Apostilava Java EE 5 - 2007
Apostilava Java EE 5 - 2007Apostilava Java EE 5 - 2007
Apostilava Java EE 5 - 2007
Rafael Benevides
 
Como escolher o Framework Java para web?
Como escolher o Framework Java para web?Como escolher o Framework Java para web?
Como escolher o Framework Java para web?
Anderson Araújo
 
Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Paradigmas de Linguagens de Programação - Modularização, componentização e re...Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Adriano Teixeira de Souza
 
JADE+JENA
JADE+JENAJADE+JENA
CDI Extensions e DeltaSpike
CDI Extensions e DeltaSpikeCDI Extensions e DeltaSpike
CDI Extensions e DeltaSpike
Rafael Benevides
 
Precisamos falar sobre Gradle
Precisamos falar sobre GradlePrecisamos falar sobre Gradle
Precisamos falar sobre Gradle
Wellington Pinheiro
 
Java1
Java1Java1
Spring framework 2.5
Spring framework 2.5Spring framework 2.5
Spring framework 2.5
Diego Pacheco
 

Semelhante a better faster stronger dagger (20)

(A10) LabMM3 - JavaScript - Subalgoritmos
(A10) LabMM3 - JavaScript - Subalgoritmos(A10) LabMM3 - JavaScript - Subalgoritmos
(A10) LabMM3 - JavaScript - Subalgoritmos
 
Programando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um FrameworkProgramando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um Framework
 
TDC 2014 SP - E o DeltaSpike ?
TDC 2014 SP - E o DeltaSpike ?TDC 2014 SP - E o DeltaSpike ?
TDC 2014 SP - E o DeltaSpike ?
 
Ecosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_javEcosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_jav
 
Dependency injection WTF? - PHPSC Conference 2012
Dependency injection WTF? - PHPSC Conference 2012Dependency injection WTF? - PHPSC Conference 2012
Dependency injection WTF? - PHPSC Conference 2012
 
T10_LM3: Subalgoritmos/funções (2013-2014)
T10_LM3: Subalgoritmos/funções (2013-2014)T10_LM3: Subalgoritmos/funções (2013-2014)
T10_LM3: Subalgoritmos/funções (2013-2014)
 
Testando Rails apps com RSpec
Testando Rails apps com RSpecTestando Rails apps com RSpec
Testando Rails apps com RSpec
 
Introdução ao Zend Framework 2
Introdução ao Zend Framework 2Introdução ao Zend Framework 2
Introdução ao Zend Framework 2
 
LabMM3 - Aula teórica 08
LabMM3 - Aula teórica 08LabMM3 - Aula teórica 08
LabMM3 - Aula teórica 08
 
Spring & Struts
Spring & StrutsSpring & Struts
Spring & Struts
 
VRaptor4
VRaptor4VRaptor4
VRaptor4
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
Apostilava Java EE 5 - 2007
Apostilava Java EE 5 - 2007Apostilava Java EE 5 - 2007
Apostilava Java EE 5 - 2007
 
Como escolher o Framework Java para web?
Como escolher o Framework Java para web?Como escolher o Framework Java para web?
Como escolher o Framework Java para web?
 
Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Paradigmas de Linguagens de Programação - Modularização, componentização e re...Paradigmas de Linguagens de Programação - Modularização, componentização e re...
Paradigmas de Linguagens de Programação - Modularização, componentização e re...
 
JADE+JENA
JADE+JENAJADE+JENA
JADE+JENA
 
CDI Extensions e DeltaSpike
CDI Extensions e DeltaSpikeCDI Extensions e DeltaSpike
CDI Extensions e DeltaSpike
 
Precisamos falar sobre Gradle
Precisamos falar sobre GradlePrecisamos falar sobre Gradle
Precisamos falar sobre Gradle
 
Java1
Java1Java1
Java1
 
Spring framework 2.5
Spring framework 2.5Spring framework 2.5
Spring framework 2.5
 

Mais de tdc-globalcode

TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidadeTDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
tdc-globalcode
 
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
tdc-globalcode
 
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de SucessoTDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
tdc-globalcode
 
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPATDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
tdc-globalcode
 
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVinoTDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
tdc-globalcode
 
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
tdc-globalcode
 
TDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devicesTDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devices
tdc-globalcode
 
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca PublicaTrilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
tdc-globalcode
 
Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#
tdc-globalcode
 
TDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case EasylocusTDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case Easylocus
tdc-globalcode
 
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
tdc-globalcode
 
TDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em GolangTDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em Golang
tdc-globalcode
 
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QATDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
tdc-globalcode
 
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendenciaTDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
tdc-globalcode
 
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR ServiceTDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
tdc-globalcode
 
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NETTDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
tdc-globalcode
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
tdc-globalcode
 
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
tdc-globalcode
 
TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#
tdc-globalcode
 
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net CoreTDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
tdc-globalcode
 

Mais de tdc-globalcode (20)

TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidadeTDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
 
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
 
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de SucessoTDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
 
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPATDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
 
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVinoTDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
 
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
 
TDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devicesTDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devices
 
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca PublicaTrilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
 
Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#
 
TDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case EasylocusTDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case Easylocus
 
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
 
TDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em GolangTDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em Golang
 
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QATDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
 
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendenciaTDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
 
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR ServiceTDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
 
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NETTDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
 
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
 
TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#
 
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net CoreTDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
 

Último

Vogais Ilustrados para alfabetização infantil
Vogais Ilustrados para alfabetização infantilVogais Ilustrados para alfabetização infantil
Vogais Ilustrados para alfabetização infantil
mamaeieby
 
A dinâmica da população mundial de acordo com as teorias populacionais.pptx
A dinâmica da população mundial de acordo com as teorias populacionais.pptxA dinâmica da população mundial de acordo com as teorias populacionais.pptx
A dinâmica da população mundial de acordo com as teorias populacionais.pptx
ReinaldoSouza57
 
- TEMPLATE DA PRATICA - Psicomotricidade.pptx
- TEMPLATE DA PRATICA - Psicomotricidade.pptx- TEMPLATE DA PRATICA - Psicomotricidade.pptx
- TEMPLATE DA PRATICA - Psicomotricidade.pptx
LucianaCristina58
 
D20 - Descritores SAEB de Língua Portuguesa
D20 - Descritores SAEB de Língua PortuguesaD20 - Descritores SAEB de Língua Portuguesa
D20 - Descritores SAEB de Língua Portuguesa
eaiprofpolly
 
livro ciclo da agua educação infantil.pdf
livro ciclo da agua educação infantil.pdflivro ciclo da agua educação infantil.pdf
livro ciclo da agua educação infantil.pdf
cmeioctaciliabetesch
 
Leonardo da Vinci .pptx
Leonardo da Vinci                  .pptxLeonardo da Vinci                  .pptx
Leonardo da Vinci .pptx
TomasSousa7
 
Atividades de Inglês e Espanhol para Imprimir - Alfabetinho
Atividades de Inglês e Espanhol para Imprimir - AlfabetinhoAtividades de Inglês e Espanhol para Imprimir - Alfabetinho
Atividades de Inglês e Espanhol para Imprimir - Alfabetinho
MateusTavares54
 
GÊNERO TEXTUAL - POEMA.pptx
GÊNERO      TEXTUAL     -     POEMA.pptxGÊNERO      TEXTUAL     -     POEMA.pptx
GÊNERO TEXTUAL - POEMA.pptx
Marlene Cunhada
 
Aula história , caracteristicas e esteriótipos em relação a DANÇA DE SALAO.pptx
Aula história , caracteristicas e esteriótipos em relação a DANÇA DE SALAO.pptxAula história , caracteristicas e esteriótipos em relação a DANÇA DE SALAO.pptx
Aula história , caracteristicas e esteriótipos em relação a DANÇA DE SALAO.pptx
edivirgesribeiro1
 
347018542-PAULINA-CHIZIANE-Balada-de-Amor-ao-Vento-pdf.pdf
347018542-PAULINA-CHIZIANE-Balada-de-Amor-ao-Vento-pdf.pdf347018542-PAULINA-CHIZIANE-Balada-de-Amor-ao-Vento-pdf.pdf
347018542-PAULINA-CHIZIANE-Balada-de-Amor-ao-Vento-pdf.pdf
AntnioManuelAgdoma
 
cronograma-enem-2024-planejativo-estudos.pdf
cronograma-enem-2024-planejativo-estudos.pdfcronograma-enem-2024-planejativo-estudos.pdf
cronograma-enem-2024-planejativo-estudos.pdf
todorokillmepls
 
epidemias endemia-pandemia-e-epidemia (1).ppt
epidemias endemia-pandemia-e-epidemia (1).pptepidemias endemia-pandemia-e-epidemia (1).ppt
epidemias endemia-pandemia-e-epidemia (1).ppt
MarceloMonteiro213738
 
Sistema de Bibliotecas UCS - Chronica do emperador Clarimundo, donde os reis ...
Sistema de Bibliotecas UCS - Chronica do emperador Clarimundo, donde os reis ...Sistema de Bibliotecas UCS - Chronica do emperador Clarimundo, donde os reis ...
Sistema de Bibliotecas UCS - Chronica do emperador Clarimundo, donde os reis ...
Biblioteca UCS
 
Livro: Pedagogia do Oprimido - Paulo Freire
Livro: Pedagogia do Oprimido - Paulo FreireLivro: Pedagogia do Oprimido - Paulo Freire
Livro: Pedagogia do Oprimido - Paulo Freire
WelberMerlinCardoso
 
Sinais de pontuação
Sinais de pontuaçãoSinais de pontuação
Sinais de pontuação
Mary Alvarenga
 
000. Para rezar o terço - Junho - mês do Sagrado Coração de Jesús.pdf
000. Para rezar o terço - Junho - mês do Sagrado Coração de Jesús.pdf000. Para rezar o terço - Junho - mês do Sagrado Coração de Jesús.pdf
000. Para rezar o terço - Junho - mês do Sagrado Coração de Jesús.pdf
YeniferGarcia36
 
759-fortaleza-resultado-definitivo-prova-objetiva-2024-05-28.pdf
759-fortaleza-resultado-definitivo-prova-objetiva-2024-05-28.pdf759-fortaleza-resultado-definitivo-prova-objetiva-2024-05-28.pdf
759-fortaleza-resultado-definitivo-prova-objetiva-2024-05-28.pdf
MessiasMarianoG
 
Estrutura Pedagógica - Laboratório de Educação a Distância.ppt
Estrutura Pedagógica - Laboratório de Educação a Distância.pptEstrutura Pedagógica - Laboratório de Educação a Distância.ppt
Estrutura Pedagógica - Laboratório de Educação a Distância.ppt
livrosjovert
 
Rimas, Luís Vaz de Camões. pptx
Rimas, Luís Vaz de Camões.          pptxRimas, Luís Vaz de Camões.          pptx
Rimas, Luís Vaz de Camões. pptx
TomasSousa7
 
atividade 8º ano entrevista - com tirinha
atividade 8º ano entrevista - com tirinhaatividade 8º ano entrevista - com tirinha
atividade 8º ano entrevista - com tirinha
Suzy De Abreu Santana
 

Último (20)

Vogais Ilustrados para alfabetização infantil
Vogais Ilustrados para alfabetização infantilVogais Ilustrados para alfabetização infantil
Vogais Ilustrados para alfabetização infantil
 
A dinâmica da população mundial de acordo com as teorias populacionais.pptx
A dinâmica da população mundial de acordo com as teorias populacionais.pptxA dinâmica da população mundial de acordo com as teorias populacionais.pptx
A dinâmica da população mundial de acordo com as teorias populacionais.pptx
 
- TEMPLATE DA PRATICA - Psicomotricidade.pptx
- TEMPLATE DA PRATICA - Psicomotricidade.pptx- TEMPLATE DA PRATICA - Psicomotricidade.pptx
- TEMPLATE DA PRATICA - Psicomotricidade.pptx
 
D20 - Descritores SAEB de Língua Portuguesa
D20 - Descritores SAEB de Língua PortuguesaD20 - Descritores SAEB de Língua Portuguesa
D20 - Descritores SAEB de Língua Portuguesa
 
livro ciclo da agua educação infantil.pdf
livro ciclo da agua educação infantil.pdflivro ciclo da agua educação infantil.pdf
livro ciclo da agua educação infantil.pdf
 
Leonardo da Vinci .pptx
Leonardo da Vinci                  .pptxLeonardo da Vinci                  .pptx
Leonardo da Vinci .pptx
 
Atividades de Inglês e Espanhol para Imprimir - Alfabetinho
Atividades de Inglês e Espanhol para Imprimir - AlfabetinhoAtividades de Inglês e Espanhol para Imprimir - Alfabetinho
Atividades de Inglês e Espanhol para Imprimir - Alfabetinho
 
GÊNERO TEXTUAL - POEMA.pptx
GÊNERO      TEXTUAL     -     POEMA.pptxGÊNERO      TEXTUAL     -     POEMA.pptx
GÊNERO TEXTUAL - POEMA.pptx
 
Aula história , caracteristicas e esteriótipos em relação a DANÇA DE SALAO.pptx
Aula história , caracteristicas e esteriótipos em relação a DANÇA DE SALAO.pptxAula história , caracteristicas e esteriótipos em relação a DANÇA DE SALAO.pptx
Aula história , caracteristicas e esteriótipos em relação a DANÇA DE SALAO.pptx
 
347018542-PAULINA-CHIZIANE-Balada-de-Amor-ao-Vento-pdf.pdf
347018542-PAULINA-CHIZIANE-Balada-de-Amor-ao-Vento-pdf.pdf347018542-PAULINA-CHIZIANE-Balada-de-Amor-ao-Vento-pdf.pdf
347018542-PAULINA-CHIZIANE-Balada-de-Amor-ao-Vento-pdf.pdf
 
cronograma-enem-2024-planejativo-estudos.pdf
cronograma-enem-2024-planejativo-estudos.pdfcronograma-enem-2024-planejativo-estudos.pdf
cronograma-enem-2024-planejativo-estudos.pdf
 
epidemias endemia-pandemia-e-epidemia (1).ppt
epidemias endemia-pandemia-e-epidemia (1).pptepidemias endemia-pandemia-e-epidemia (1).ppt
epidemias endemia-pandemia-e-epidemia (1).ppt
 
Sistema de Bibliotecas UCS - Chronica do emperador Clarimundo, donde os reis ...
Sistema de Bibliotecas UCS - Chronica do emperador Clarimundo, donde os reis ...Sistema de Bibliotecas UCS - Chronica do emperador Clarimundo, donde os reis ...
Sistema de Bibliotecas UCS - Chronica do emperador Clarimundo, donde os reis ...
 
Livro: Pedagogia do Oprimido - Paulo Freire
Livro: Pedagogia do Oprimido - Paulo FreireLivro: Pedagogia do Oprimido - Paulo Freire
Livro: Pedagogia do Oprimido - Paulo Freire
 
Sinais de pontuação
Sinais de pontuaçãoSinais de pontuação
Sinais de pontuação
 
000. Para rezar o terço - Junho - mês do Sagrado Coração de Jesús.pdf
000. Para rezar o terço - Junho - mês do Sagrado Coração de Jesús.pdf000. Para rezar o terço - Junho - mês do Sagrado Coração de Jesús.pdf
000. Para rezar o terço - Junho - mês do Sagrado Coração de Jesús.pdf
 
759-fortaleza-resultado-definitivo-prova-objetiva-2024-05-28.pdf
759-fortaleza-resultado-definitivo-prova-objetiva-2024-05-28.pdf759-fortaleza-resultado-definitivo-prova-objetiva-2024-05-28.pdf
759-fortaleza-resultado-definitivo-prova-objetiva-2024-05-28.pdf
 
Estrutura Pedagógica - Laboratório de Educação a Distância.ppt
Estrutura Pedagógica - Laboratório de Educação a Distância.pptEstrutura Pedagógica - Laboratório de Educação a Distância.ppt
Estrutura Pedagógica - Laboratório de Educação a Distância.ppt
 
Rimas, Luís Vaz de Camões. pptx
Rimas, Luís Vaz de Camões.          pptxRimas, Luís Vaz de Camões.          pptx
Rimas, Luís Vaz de Camões. pptx
 
atividade 8º ano entrevista - com tirinha
atividade 8º ano entrevista - com tirinhaatividade 8º ano entrevista - com tirinha
atividade 8º ano entrevista - com tirinha
 

better faster stronger dagger

  • 2. Rafael Toledo @_rafaeltoledo Android Developer @ Concrete Solutions www.rafaeltoledo.net
  • 3. O que é Injeção de Dependência? @_rafaeltoledo
  • 4. “Injeção de Dependência (ou Dependency Injection, em inglês) é um padrão de desenvolvimento de programas de computadores utilizado quando é necessário manter baixo o nível de acoplamento entre diferentes módulos de um sistema. (...)” @_rafaeltoledo
  • 5. “Nesta solução as dependências entre os módulos não são definidas programaticamente, mas sim pela configuração de uma infraestrutura de software (container) que é responsável por "injetar" em cada componente suas dependências declaradas. A Injeção de dependência se relaciona com o padrão Inversão de controle mas não pode ser considerada um sinônimo deste.” Wikipedia, 2015 @_rafaeltoledo
  • 7. Diz respeito a separação de onde os objetos são criados e onde são utilizados @_rafaeltoledo
  • 8. Em vez de criar, você pede @_rafaeltoledo
  • 9. class UserController { void doLogic() { try { User user = RetrofitApi.getInstance().getUser(1); new UserDaoImpl().save(user); Logger.getForClass(UserController.class).log("Success"); } catch (IOException e) { Logger.getForClass(UserController.class).logException(e); } } } @_rafaeltoledo
  • 10. class UserController { UserDaoImpl dao; Logger logger; UserApi api; void doLogic() { try { api = RetrofitApi.getInstance(); User user = api.getUser(1); dao = new UserDaoImpl(); dao.save(user); logger = Logger.getForClass(UserController.class); logger.log("Success"); } catch (IOException e) { logger = Logger.getForClass(UserController.class); logger.logException(e); } } } @_rafaeltoledo
  • 11. class UserController { UserDao dao; // Interface! Logger logger; Api api; void doLogic() { try { if (api == null) api = RetrofitApi.getInstance(); User user = api.getUser(1); if (dao == null) dao = new UserDaoImpl(); dao.save(user); if (logger == null) logger = Logger.getForClass(UserController.class); logger.log("Success"); } catch (IOException e) { if (logger == null) logger = Logger.getForClass(UserController.class); logger.logException(e); } } } @_rafaeltoledo
  • 12. class UserController { UserDao dao = new UserDaoImpl(); Logger logger = Logger.getForClass(UserController.class); Api api = RetrofitApi.getInstance(); void doLogic() { try { User user = api.getUser(1); dao.save(user); logger.log("Success"); } catch (IOException e) { logger.logException(e); } } } @_rafaeltoledo
  • 13. class UserController { UserDao dao; Logger logger; Api api; public UserController() { dao = new UserDaoImpl(); api = RetrofitApi.getInstance(); logger = Logger.getForClass(UserController.class); } void doLogic() { try { User user = api.getUser(1); dao.save(user); logger.log("Success"); } catch (IOException e) { logger.logException(e); } } } @_rafaeltoledo
  • 14. class UserController { UserDao dao; Logger logger; Api api; public UserController() { dao = new UserDaoImpl(); api = RetrofitApi.getInstance(); logger = Logger.getForClass(UserController.class); } void doLogic() { try { User user = api.getUser(1); dao.save(user); logger.log("Success"); } catch (IOException e) { logger.logException(e); } } } @_rafaeltoledo
  • 15. class UserController { UserDao dao; Logger logger; Api api; public UserController() { dao = new UserDaoImpl(); api = RetrofitApi.getInstance(); logger = Logger.getForClass(UserController.class); } void doLogic() { try { User user = api.getUser(1); dao.save(user); logger.log("Success"); } catch (IOException e) { logger.logException(e); } } } @_rafaeltoledo
  • 16. class UserController { UserDao dao; Logger logger; Api api; public UserController() { dao = new UserDaoImpl(); api = RetrofitApi.getInstance(); logger = Logger.getForClass(UserController.class); } void doLogic() { try { User user = api.getUser(1); dao.save(user); logger.log("Success"); } catch (IOException e) { logger.logException(e); } } } @_rafaeltoledo
  • 22. class UserDaoImpl implements UserDao { public UserDaoImpl() { //... } } @_rafaeltoledo
  • 23. class UserDaoImpl implements UserDao { public UserDaoImpl(Context context) { //... } } @_rafaeltoledo
  • 25. Alteração em todas as classes! @_rafaeltoledo
  • 26. Alteração em todas as classes! Muito retrabalho! @_rafaeltoledo
  • 27. Alteração em todas as classes! Muito retrabalho! @_rafaeltoledo
  • 28. Alteração em todas as classes! Muito retrabalho! @_rafaeltoledo
  • 29. class UserController { UserDao dao; Logger logger; Api api; public UserController() { dao = new UserDaoImpl(); api = RetrofitApi.getInstance(); logger = Logger.getForClass(UserController.class); } void doLogic() { try { User user = api.getUser(1); dao.save(user); logger.log("Success"); } catch (IOException e) { logger.logException(e); } } } @_rafaeltoledo
  • 30. class UserController { UserDao dao; Logger logger; Api api; public UserController() { dao = new UserDaoImpl(); api = RetrofitApi.getInstance(); logger = Logger.getForClass(UserController.class); } void doLogic() { try { User user = api.getUser(1); dao.save(user); logger.log("Success"); } catch (IOException e) { logger.logException(e); } } } @_rafaeltoledo
  • 31. class UserController { UserDao dao; Logger logger; Api api; public UserController(UserDao dao, Api api, Logger logger) { this.dao = dao; this.api = api; this.logger = logger; } void doLogic() { try { User user = api.getUser(1); dao.save(user); logger.log("Success"); } catch (IOException e) { logger.logException(e); } } } @_rafaeltoledo
  • 32. DI: Separação do uso e criação de objetos @_rafaeltoledo
  • 33. DI: Separação do uso e criação de objetos não há a necessidade de bibliotecas ou frameworks! @_rafaeltoledo
  • 35. Spring, Guice, Dagger 1 & cia #oldbutgold @_rafaeltoledo
  • 36. Spring, Guice, Dagger 1 & cia #oldbutnot @_rafaeltoledo
  • 39. Dagger 2 ● Fork do Dagger, da Square, feito pela Google ● Elimina todo o uso de reflections ● Construída sobre as anotações javax. inject da especificação JSR-330 @_rafaeltoledo
  • 40. Dagger 2 ● Validação de todo o grafo de dependências em tempo de compilação ● Menos flexível, se comparado ao Dagger 1 - ex.: não possui module overriding ● Proguard configuration-free @_rafaeltoledo
  • 41. Dagger 2 ● API enxuta! ● Código gerado é debugger-friendly ● Muito performático ● google.github.io/dagger @_rafaeltoledo
  • 42. public @interface Component { Class<?>[] modules() default {}; Class<?>[] dependencies() default {}; } public @interface Subcomponent { Class<?>[] includes() default {}; } public @interface Module { Class<?>[] includes() default {}; } public @interface Provides { } public @interface MapKey { boolean unwrapValue() default true; } public interface Lazy<T> { T get(); } @_rafaeltoledo
  • 43. // JSR-330 public @interface Inject { } public @interface Scope { } public @interface Qualifier { } @_rafaeltoledo
  • 44. Como integro no meu projeto? @_rafaeltoledo
  • 45. // build.gradle buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.3.1' } } allprojects { repositories { jcenter() } } @_rafaeltoledo
  • 46. // build.gradle buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.3.1' } } allprojects { repositories { jcenter() } } @_rafaeltoledo
  • 47. // build.gradle buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.3.1' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } allprojects { repositories { jcenter() } } @_rafaeltoledo
  • 48. apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion '23.0.1' defaultConfig { applicationId 'net.rafaeltoledo.tdc2015' minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName '1.0' } } dependencies { compile 'com.android.support:appcompat-v7:23.0.1' } @_rafaeltoledo
  • 49. apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt' android { compileSdkVersion 23 buildToolsVersion '23.0.1' defaultConfig { applicationId 'net.rafaeltoledo.tdc2015' minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName '1.0' } } dependencies { compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.google.dagger:dagger:2.0.1' apt 'com.google.dagger:dagger-compiler:2.0.1' provided 'javax.annotation:javax.annotation-api:1.2' } @_rafaeltoledo
  • 50. apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.android-apt' android { compileSdkVersion 23 buildToolsVersion '23.0.1' defaultConfig { applicationId 'net.rafaeltoledo.tdc2015' minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName '1.0' } } dependencies { compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.google.dagger:dagger:2.0.1' apt 'com.google.dagger:dagger-compiler:2.0.1' provided 'javax.annotation:javax.annotation-api:1.2' // JSR-330 } @_rafaeltoledo
  • 54. @Inject ● Parte da JSR-330 ● Marca quais dependências devem ser fornecidas pelo Dagger ● Pode aparecer de 3 formas no código @_rafaeltoledo
  • 55. public class TdcActivityPresenter { private TdcActivity activity; private TdcDataStore dataStore; @Inject public TdcActivityPresenter(TdcActivity activity, TdcDataStore dataStore) { this.activity = activity; this.dataStore = dataStore; } } 1. No Construtor @_rafaeltoledo
  • 56. 1. No Construtor ● Todas as dependências vem do grafo de dependências do Dagger ● Anotar uma classe dessa forma faz com que ela também faça parte do grafo de dependências (podendo ser injetada em outras classes) @_rafaeltoledo
  • 57. 1. No Construtor ● Limitação: não podemos anotar mais que um construtor com a anotação @Inject @_rafaeltoledo
  • 58. public class TdcActivity extends AppCompatActivity { @Inject TdcActivityPresenter presenter; @Inject SharedPreferences preferences; @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); getComponent().inject(this); } } 2. Nos Atributos da Classe @_rafaeltoledo
  • 59. 2. Nos Atributos da Classe ● A injeção nesse caso deve ser manual, caso contrários os atributos serão todos nulos @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); getComponent().inject(this); } ● Limitação: os atributos não podem ser privados! @_rafaeltoledo
  • 60. public class TdcActivityPresenter { private TdcActivity activity; @Inject public TdcActivityPresenter(TdcActivity activity) { this.activity = activity; } @Inject public void enableAnalytics(AnalyticsManager analytics) { analytics.track(this); } } 3. Em métodos públicos @_rafaeltoledo
  • 61. 3. Em métodos públicos ● Utilizado em conjunto com a anotação no construtor da classe ● Para casos onde o objeto injetado necessitamos da instância da própria classe na dependência fornecida @Inject public void enableAnalytics(AnalyticsManager analytics) { analytics.track(this); } @_rafaeltoledo
  • 62. 3. Em métodos públicos ● O método anotado é chamado automaticamente logo após o construtor @_rafaeltoledo
  • 63. @Module ● Parte da API do Dagger ● Utilizada para identificar classes que fornecem dependências @_rafaeltoledo
  • 64. @Module public class DataModule { @Provides @Singleton public OkHttpClient provideOkHttpClient() { OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS); okHttpClient.setReadTimeout(10, TimeUnit.SECONDS); okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS); return okHttpClient; } @Provides @Singleton public RestAdapter provideRestAdapter(OkHttpClient client) { return new RestAdapter.Builder() .setClient(new OkClient(okHttpClient)) .setEndpoint("https://api.github.com") .build(); } } @_rafaeltoledo
  • 65. @Module public class DataModule { @Provides @Singleton public OkHttpClient provideOkHttpClient() { OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS); okHttpClient.setReadTimeout(10, TimeUnit.SECONDS); okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS); return okHttpClient; } @Provides @Singleton public RestAdapter provideRestAdapter(OkHttpClient client) { return new RestAdapter.Builder() .setClient(new OkClient(okHttpClient)) .setEndpoint("https://api.github.com") .build(); } } @_rafaeltoledo
  • 66. @Provides ● Utilizada nas classes anotadas como @Module para identificar quais métodos retornam dependências @_rafaeltoledo
  • 67. @Module public class DataModule { @Provides @Singleton public OkHttpClient provideOkHttpClient() { OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS); okHttpClient.setReadTimeout(10, TimeUnit.SECONDS); okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS); return okHttpClient; } @Provides @Singleton public RestAdapter provideRestAdapter(OkHttpClient client) { return new RestAdapter.Builder() .setClient(new OkClient(okHttpClient)) .setEndpoint("https://api.github.com") .build(); } } @_rafaeltoledo
  • 68. @Module public class DataModule { @Provides @Singleton public OkHttpClient provideOkHttpClient() { OkHttpClient okHttpClient = new OkHttpClient(); okHttpClient.setConnectionTimeout(10, TimeUnit.SECONDS); okHttpClient.setReadTimeout(10, TimeUnit.SECONDS); okHttpClient.setWriteTimeout(10, TimeUnit.SECONDS); return okHttpClient; } @Provides @Singleton public RestAdapter provideRestAdapter(OkHttpClient client) { return new RestAdapter.Builder() .setClient(new OkClient(okHttpClient)) .setEndpoint("https://api.github.com") .build(); } } @_rafaeltoledo
  • 69. @Component ● É a anotação que liga os @Modules aos @Injects ● É colocada em uma interface ● Define quais módulos possui, quem será injetado @_rafaeltoledo
  • 70. @Component ● Precisa especificar obrigatoriamente seu escopo (ciclo de vida de suas dependências) ● Pode publicar dependências ● Pode possuir outros componentes @_rafaeltoledo
  • 71. @Singleton @Component( modules = { DataModule.class, UiModule.class } ) public interface TdcAppComponent { void inject(TdcApplication app); MainActivity inject(MainActivity activity); Application getApplication(); AnalyticsManager getAnalyticsManager(); } @_rafaeltoledo
  • 72. @Singleton // Escopo @Component( modules = { DataModule.class, UiModule.class } ) public interface TdcAppComponent { void inject(TdcApplication app); MainActivity inject(MainActivity activity); Application getApplication(); AnalyticsManager getAnalyticsManager(); } @_rafaeltoledo
  • 73. @Singleton @Component( modules = { DataModule.class, UiModule.class } ) public interface TdcAppComponent { void inject(TdcApplication app); MainActivity inject(MainActivity activity); Application getApplication(); AnalyticsManager getAnalyticsManager(); } @_rafaeltoledo
  • 74. @Singleton @Component( modules = { DataModule.class, UiModule.class } ) public interface TdcAppComponent { void inject(TdcApplication app); MainActivity inject(MainActivity activity); // Caso queira encadear Application getApplication(); AnalyticsManager getAnalyticsManager(); } @_rafaeltoledo
  • 75. @Singleton @Component( modules = { DataModule.class, UiModule.class } ) public interface TdcAppComponent { void inject(TdcApplication app); MainActivity inject(MainActivity activity); Application getApplication(); AnalyticsManager getAnalyticsManager(); // Dependências visíveis } // para outros componentes* @_rafaeltoledo
  • 76. @Singleton @Component( modules = { DataModule.class, UiModule.class } ) public interface TdcAppComponent { void inject(TdcApplication app); MainActivity inject(MainActivity activity); Application getApplication(); AnalyticsManager getAnalyticsManager(); } @_rafaeltoledo
  • 77. @ActivityScope // Escopo personalizado @Component( modules = TdcActivityModule.class, dependencies = TdcComponent.class ) public interface TdcActivityComponent { TdcActivity inject(TdcActivity activity); TdcActivityPresenter presenter(); } @_rafaeltoledo
  • 78. @Generated("dagger.internal.codegen.ComponentProcessor") public final class DaggerMainComponent implements MainComponent { private Provider<ApiService> provideApiServiceProvider; private MembersInjector<MainActivity> mainActivityMembersInjector; private DaggerMainComponent(Builder builder) { assert builder != null; initialize(builder); } public static Builder builder() { return new Builder(); } public static MainComponent create() { return builder().build(); } private void initialize(final Builder builder) { this.provideApiServiceProvider = ScopedProvider.create(MainModule_ProvideApiServiceFactory.create(builder.mainModule)); this.mainActivityMembersInjector = MainActivity_MembersInjector.create( (MembersInjector) MembersInjectors.noOp(), provideApiServiceProvider); } @Override public void inject(MainActivity activity) { mainActivityMembersInjector.injectMembers(activity); } } @_rafaeltoledo
  • 79. public class TdcApp extends Application { TdcAppComponent component; @Override public void onCreate() { component = DaggerTdcAppComponent.create(); component = DaggerTdcAppComponent.builder() .dataModule(new DataModule(this)) // Módulo com construtor .build(); // parametrizado } } Instanciando um Componente @_rafaeltoledo
  • 81. Escopo = ciclo de vida do grafo de dependências (componente) @_rafaeltoledo
  • 82. @Singleton @Component( modules = { DataModule.class, UiModule.class } ) public interface TdcAppComponent { void inject(TdcApplication app); MainActivity inject(MainActivity activity); Application getApplication(); AnalyticsManager getAnalyticsManager(); } @_rafaeltoledo
  • 83. @ActivityScope // Escopo personalizado @Component( modules = TdcActivityModule.class, dependencies = TdcComponent.class ) public interface TdcActivityComponent { TdcActivity inject(TdcActivity activity); TdcActivityPresenter presenter(); } @_rafaeltoledo
  • 84. @Scope @Retention(RetentionPolicy.RUNTIME) public @interface UserScope { } Definição de um escopo @_rafaeltoledo
  • 85. Exemplo de uso Miroslaw Stanek frogermcs.github.io @_rafaeltoledo
  • 86. @Singleton @Component(modules = DataModule.class) public interface TdcAppComponent { UserComponent plus(UserModule module); // não é necessário expor as dependências } Implementação @_rafaeltoledo
  • 87. @UserScope @Subcomponent(modules = UserModule.class) public interface UserComponent { UserActivityComponent plus(UserActivityModule module); } Implementação @_rafaeltoledo
  • 88. public class TdcApp extends Application { TdcAppComponent component; UserComponent userComponent; public UserComponent createUserComponent(User user) { userComponent = component.plus(new UserModule(user)); return userComponent; } public void releaseUserComponent() { userComponent = null; } ... } Implementação @_rafaeltoledo
  • 89. Dagger 2 Outras coisas legais! @_rafaeltoledo
  • 90. @Inject Lazy<SharedPreferences> prefs; void salvar() { prefs.get().edit().putString("status", "ok!").apply(); } Dependências “Preguiçosas” @_rafaeltoledo
  • 91. // No módulo @Provides @Singleton @ApiUrl String provideApiUrl(Context context) { return context.getString(R.string.api_url); } @Provides @Singleton @AccessToken String provideRestAdapter(SharedPreferences prefs) { return prefs.getString("token", null); } // Na classe a ser injetada @Inject @AccessToken String accessToken; Qualificadores @_rafaeltoledo
  • 92. // Declarando sua anotação @MapKey(unwrapValue = true) @interface GroupKey { String value(); } @MapKey @_rafaeltoledo
  • 93. // Fornecendo dependências no módulo @Provides(type = Type.MAP) @GroupKey("um") String provideFirstValue() { return "primeiro valor"; } @Provides(type = Type.MAP) @GroupKey("dois") String provideSecondValue() { return "segundo valor"; } @MapKey @_rafaeltoledo
  • 94. // Uso @Inject Map<String, String> map; // {um=primeiro valor, dois=segundo valor} Por enquanto, só aceita Map e Set, e valores do tipo String e Enumeradores @MapKey @_rafaeltoledo
  • 95. Ok! Tudo muito bonito mas... @_rafaeltoledo
  • 96. O que eu ganho de fato com tudo isso? @_rafaeltoledo
  • 97. Grandes benefícios ● Código mais limpo e organizado ● Melhorias no gerenciamento de objetos (melhor controle de singletons) ● Código mais fácil de TESTAR @_rafaeltoledo
  • 98. Dagger 2 e Testes ● Programar orientado a interfaces - mocks ● Sobrescrita de Componentes e Módulos @_rafaeltoledo
  • 99. Dagger 2 e Testes @Module public class TestMainModule { @Provides // Poderíamos fazer com o Retrofit Mock! public ApiService provideApiService() { return new ApiService() { @Override public List<Repo> listRepos() { return Arrays.asList( new Repo("my-test-repo"), new Repo("another-test-repo") ); } }; } } @_rafaeltoledo
  • 100. Dagger 2 e Testes @Component(modules = DebugMainModule.class) public interface TestMainComponent extends MainComponent { } @_rafaeltoledo
  • 101. Dagger 2 e Espresso 2 @RunWith(AndroidJUnit4.class) public class MainActivityTest { // ... @Before public void setUp() { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); MainApplication app = (MainApplication) instrumentation.getTargetContext().getApplicationContext(); app.setComponent(DaggerDebugMainComponent.create()); rule.launchActivity(new Intent()); } } @_rafaeltoledo
  • 102. Dagger 2 e Robolectric 3 @RunWith(RobolectricGradleTestRunner.class) @Config(sdk = 21, constants = BuildConfig.class) public class MainActivityTest { // ... @Before public void setUp() { MainComponent component = DaggerDebugMainComponent.create(); MainApplication app = ((MainApplication) RuntimeEnvironment.application) .setComponent(component); } } @_rafaeltoledo
  • 104. Para saber mais ● Site oficial - google.github.io/dagger ● Dagger 2 - A New Type of Dependency Injection (Gregory Kick) - vai.la/fdwt ● The Future of Dependency Injection with Dagger 2 (Jake Wharton) - vai.la/fdwy ● froger_mcs Dev Blog - frogermcs.github.io
  • 105. OBRIGADO! rafaeltoledo.net @_rafaeltoledo Desenv. Android @ Concrete Solutions concretesolutions.com.br/carreira