SlideShare a Scribd company logo
1 of 97
Download to read offline
Clean code via
 Dependency Injection + Guice


                                @jordi9
bit.ly/devfest12cleancode   9 noviembre 2012
... shameless self-promotion bro!
About you
Gang of Four?
Legacy Code?
Dependency Injection?
Monkey patching?
Monkey testing?
Unit testing?
TDD / BDD?
Agile? XP? Scrum what?
S.O.L.I.D.
Single responsibility principle
Open/closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
Legacy code is code without test
F.I.R.S.T.
Fast Run hundreds or thousands per second
Isolated Failure reasons become obvious
Reliable Run repeatedly in any order, any time
Self-validating No manual evaluation required
Timely Written before the code
Write some code, kill technical debt
                             (or not)
Showtime!
class Showtimes {
  MovieRepository repository;

    Showtimes() {
      repository = MovieRepositoryFactory.getInstance();
    }

    Set<Movie> findMovies(City city) {
      return repository.findByCity(city);
    }
}
Smell: Constructor does real work
class Showtimes {
  MovieRepository repository;

    Showtimes() {
      repository = MovieRepositoryFactory.getInstance();
    }

    Set<Movie> findMovies(City city) {
      return repository.findByCity(city);
    }
}
Smell: Constructor does real work
class Showtimes {
  MovieRepository repository;

    Showtimes() {
      repository = MovieRepositoryFactory.getInstance();
    }

    Set<Movie> findMovies(City city) {
      return repository.findByCity(city);
    }
}
Smell: Constructor does real work
class Showtimes {
  MovieRepository repository;

    Showtimes() {
      repository = MovieRepositoryFactory.getInstance();
    }

    Set<Movie> findMovies(City city) {
      return repository.findByCity(city);
    }
}
Factory Pattern, boilerplate
public class MovieRepositoryFactory {
  static class MovieRepositoryHolder {
    static MovieRepository instance = new MovieRepositoryImpl();
  }

    public static MovieRepository getInstance() {
      return MovieRepositoryHolder.instance;
    }

    static void setInstance(MovieRepository mock) {
      MovieRepositoryHolder.instance = mock;
    }
}
Factory Pattern, boilerplate
public class MovieRepositoryFactory {
  static class MovieRepositoryHolder {
    static MovieRepository instance = new MovieRepositoryImpl();
  }

    public static MovieRepository getInstance() {
      return MovieRepositoryHolder.instance;
    }

    static void setInstance(MovieRepository mock) {
      MovieRepositoryHolder.instance = mock;
    }
}
Factory Pattern, boilerplate
public class MovieRepositoryFactory {
  static class MovieRepositoryHolder {
    static MovieRepository instance = new MovieRepositoryImpl();
  }

    public static MovieRepository getInstance() {
      return MovieRepositoryHolder.instance;
    }

    static void setInstance(MovieRepository mock) {
      MovieRepositoryHolder.instance = mock;
    }
}
Factory Pattern, boilerplate
public class MovieRepositoryFactory {
  static class MovieRepositoryHolder {
    static MovieRepository instance = new MovieRepositoryImpl();
  }

    public static MovieRepository getInstance() {
      return MovieRepositoryHolder.instance;
    }

    static void setInstance(MovieRepository mock) {
      MovieRepositoryHolder.instance = mock;
    }
}
Factory Pattern, boilerplate
public class MovieRepositoryFactory {
  static class MovieRepositoryHolder {
    static MovieRepository instance = new MovieRepositoryImpl();
  }

    public static MovieRepository getInstance() {
      return MovieRepositoryHolder.instance;
    }

    static void setInstance(MovieRepository mock) {
      MovieRepositoryHolder.instance = mock;
    }
}
Factory Pattern, boilerplate
public class MovieRepositoryFactory {
  static class MovieRepositoryHolder {
    static MovieRepository instance = new MovieRepositoryImpl();
  }

    public static MovieRepository getInstance() {
      return MovieRepositoryHolder.instance;
    }

    static void setInstance(MovieRepository mock) {
      MovieRepositoryHolder.instance = mock;
    }
}
Hard to test
@Test
void findMovies_cantTestYouDude() {
  Showtimes showtimes = new Showtimes();
  // FRAK!
  // No database setup... I'm stuck with my collaborators
  // Can't really change it... Will it run in my
  // partners computer?
}
Fix: Constructor does real work
Fix: Constructor does real work
class Showtimes {
  MovieRepository repository;

    Showtimes(MovieRepository repository) {
      this.repository = repository;
    }

    Set<Movie> findMovies(City city) {
      return repository.findByCity(city);
    }
}
Fix: Constructor does real work
class Showtimes {
  // Hollywood principle: "Don't call us, we'll call you"
  MovieRepository repository;

    Showtimes(MovieRepository repository) {
      this.repository = repository;
    }

    Set<Movie> findMovies(City city) {
      return repository.findByCity(city);
    }
}
Fix: Constructor does real work
class Showtimes {
  // Hollywood principle: "Don't call us, we'll call you"
  MovieRepository repository;

    @Inject
    Showtimes(MovieRepository repository) {
      this.repository = repository;
    }

    Set<Movie> findMovies(City city) {
      return repository.findByCity(city);
    }
}
Fix: MovieRepository creation?
class App {
  public static void main(String[] args) {
    // Manual Dependency Injection... but much more
    // boilerplate!
    // Maybe some <init> method... but that's why
    // constructors exist right?
    // Some container injection... mmm... Spring, Pico?
    // Or better, Guice time!
  }
}
Fix: MovieRepository creation
class App {
  public static void main(String[] args) {
    Injector injector = Guice.createInjector(
      new AbstractModule() {
          @Override void configure() {
           bind(MovieRepository.class)
             .to(JpaMovieRepository.class);
        }
    });

        injector.getInstance(Showtimes.class).findMovies(bcn);
    }
}
Fix: MovieRepository creation
class App {
  public static void main(String[] args) {
    Injector injector = Guice.createInjector(
      new AbstractModule() {
          @Override void configure() {
           bind(MovieRepository.class)
             .to(JpaMovieRepository.class);
        }
    });

        injector.getInstance(Showtimes.class).findMovies(bcn);
    }
}
Fix: MovieRepository creation
class App {
  public static void main(String[] args) {
     Injector injector = Guice.createInjector(
       new AbstractModule() {
           @Override void configure() {
            bind(MovieRepository.class)
              .to(JpaMovieRepository.class);
         }
     });
    // Injection is VIRAL! Avoid at all cost using the
    // Injector in more than one place (aka Service Locator)
     injector.getInstance(Showtimes.class).findMovies(bcn);
  }
}
Fix: Testable and flexible design
Showtimes showtimes;
@Mock MovieRepository repository;

@Test void findMovies_easyNow() {
  showtimes = new Showtimes(repository);

    given(repository.findByCity(bcn))
      .willReturn(ImmutableSet.of(looper));

    Set<Movie> movies = showtimes.findMovies(bcn);

    assertThat(movies, hasItem(looper));
}
Fix: Testable and flexible design
Showtimes showtimes; //SUT
@Mock MovieRepository repository;

@Test void findMovies_easyNow() {
  showtimes = new Showtimes(repository);

    given(repository.findByCity(bcn))
      .willReturn(ImmutableSet.of(looper));

    Set<Movie> movies = showtimes.findMovies(bcn);

    assertThat(movies, hasItem(looper));
}
Fix: Testable and flexible design
Showtimes showtimes; //SUT
@Mock MovieRepository repository; // <3 Mockito, BDD

@Test void findMovies_easyNow() {
  showtimes = new Showtimes(repository);
  //given
  given(repository.findByCity(bcn))
    .willReturn(ImmutableSet.of(looper));
  //when
  Set<Movie> movies = showtimes.findMovies(bcn);
  //then
  assertThat(movies, hasItem(looper));
}
Fix: Testable and flexible design
Showtimes showtimes; //SUT
@Mock MovieRepository repository; // <3 Mockito, BDD

@Test void findMovies_easyNow() {
  showtimes = new Showtimes(repository);
  //given
  given(repository.findByCity(bcn))
    .willReturn(ImmutableSet.of(looper));
  //when
  Set<Movie> movies = showtimes.findMovies(bcn);
  //then
  assertThat(movies, hasItem(looper)); // <3 Hamcrest
}
Fix: Testable and flexible design
Showtimes showtimes; //SUT
@Mock MovieRepository repository; // <3 Mockito, BDD

@Test void findMovies_easyNow() {
  showtimes = new Showtimes(repository);
  //given
  given(repository.findByCity(bcn))
    .willReturn(ImmutableSet.of(looper)); // <3 Guava
  //when
  Set<Movie> movies = showtimes.findMovies(bcn);
  //then
  assertThat(movies, hasItem(looper)); // <3 Hamcrest
}
Constructor does real work,
more flavours
Flavour: Partial objects, Law of Demeter
class Ratings {
  User user;

    Ratings(AccountManager manager) {
      user = manager.getLoggedUser();
      user.setQueue(new ItTakesForeverToBuildOSSQueue());
    }
}
Flavour: Partial objects, Law of Demeter
class Ratings {
  User user;

    Ratings(AccountManager manager) {
      user = manager.getLoggedUser();
     user.setQueue(new ItTakesForeverToBuildOSSQueue());
    }
    // Test? Slow, really slow
    // We don't use AccountManager anywhere else
}
Fix: Partial objects, Law of Demeter
class Ratings {
  User user;

    @Inject Ratings(User user) {
      this.user = user;
    }
}
Fix: Partial objects, Law of Demeter
class Ratings {
  User user;

    // How do we inject this User like we need it?
    // Where's the Queue?
    @Inject Ratings(User user) {
      this.user = user;
    }

}
Fix: Partial objects, Law of Demeter
@Provides
User providesUser(AccountManager manager, Queue queue) {
  User user = manager.getLoggedUser();
  user.setQueue(queue);
  return user;
}

@Provides @Singleton
Queue providesLongRunningQueue() {
  return new ItTakesForeverToBuildOSSQueue();
}
Fix: Partial objects, Law of Demeter
@Provides
User providesUser(AccountManager manager, Queue queue) {
  User user = manager.getLoggedUser();
  user.setQueue(queue);
  return user;
}

@Provides @Singleton
Queue providesLongRunningQueue() {
  return new ItTakesForeverToBuildOSSQueue();
}
Fix: Partial objects, Law of Demeter
@Provides
User providesUser(AccountManager manager, Queue queue) {
  User user = manager.getLoggedUser();
  user.setQueue(queue);
  return user;
}

@Provides @Singleton // no JVM Singleton, yay!
Queue providesLongRunningQueue() {
  return new ItTakesForeverToBuildOSSQueue();
}
Fix: Partial objects, Law of Demeter
@Provides
User providesUser(AccountManager manager, Queue queue) {
  User user = manager.getLoggedUser();
  user.setQueue(queue);
  return user;
}

@Provides @Singleton // no JVM Singleton, yay!
Queue providesLongRunningQueue() {
  return new ItTakesForeverToBuildOSSQueue();
}

// Provider methods should be inside a Module
Test: Partial objects, Law of Demeter
Ratings ratings; //SUT

@Test void ratings_findAverage() {
  ratings = new Ratings(new DummyUser());
  // Easy to test now, we can have a mock or test-double
  // and check everything about Ratings. We don't care
  // about collaborators.
}
Warning signs: Constructor does real work

New keyword in constructor or fields
Static method calls
Anything more than field assignments
Object not fully initialized after constructor
Control flow
Smell: Digging into Collaborators
Flavour: Digging around
class TicketPriceCalculator {
  MovieTheaterService service;

    TicketPriceCalculator(MovieTheaterService service) {
      this.service = service;
    }

    BigDecimal calculatePrice(User user, Invoice invoice) {
      UserBalance balance = user.getBalance();
      BigDecimal amount = invoice.getSubtotal();
      return service.calculateTotal(balance, amount);
    }
}
Flavour: Digging around
class TicketPriceCalculator {
  MovieTheaterService service;

    TicketPriceCalculator(MovieTheaterService service) {
      this.service = service;
    }

    BigDecimal calculatePrice(User user, Invoice invoice) {
      UserBalance balance = user.getBalance();
      BigDecimal amount = invoice.getSubtotal();
      return service.calculateTotal(balance, amount);
    }
}
Hard to test? Digging around
TicketPriceCalculator calculator; //SUT
@Mock MovieTheaterService service;

@Test void calculatePrice_tooMuchWork() {
  calculator = new TicketPriceCalculator(service);
  given(user.getBalance()).willReturn(new DummyBalance());
  given(invoice.getSubtotal()).willReturn(new BigDecimal("9.3"));

    BigDecimal result = calculator.calculatePrice(balance, invoice);

    assertThat(result, is(new BigDecimal("8.3"));
}
Hard to test? Digging around
TicketPriceCalculator calculator; //SUT
@Mock MovieTheaterService service;

@Test void calculatePrice_tooMuchWork() {
  calculator = new TicketPriceCalculator(service);
  given(user.getBalance()).willReturn(new DummyBalance());
  given(invoice.getSubtotal()).willReturn(new BigDecimal("9.3"));

    BigDecimal result = calculator.calculatePrice(balance, invoice);

    assertThat(result, is(new BigDecimal("8.3"));
}
Flavour: Digging around
class TicketPriceCalculator {
  MovieTheaterService service;

    TicketPriceCalculator(MovieTheaterService service) {
      this.service = service;
    }

    // Deceitful API, Law of Demeter
    BigDecimal calculatePrice(User user, Invoice invoice) {
      UserBalance balance = user.getBalance();
      BigDecimal amount = invoice.getSubtotal();
      return service.calculateTotal(balance, amount);
    }
}
Flavour: Digging around
class TicketPriceCalculator {
  MovieTheaterService service;

    TicketPriceCalculator(MovieTheaterService service) {
      this.service = service;
    }

    // Problem? Imagine this in a big application, your code
    // will be much more complicated than you (and your team) need
    BigDecimal calculatePrice(User user, Invoice invoice) {
      UserBalance balance = user.getBalance();
      BigDecimal amount = invoice.getSubtotal();
      return service.calculateTotal(balance, amount);
    }
}
Fix: Digging around
class TicketPriceCalculator {
  MovieTheaterService service;

    TicketPriceCalculator(MovieTheaterService service) {
      this.service = service;
    }

    // Cleaner API, forget about "Middle men" class
    BigDecimal calculatePrice(UserBalance balance, BigDecimal am) {
      return service.calculateTotal(balance, am);
    }
}
Fix: Digging around
TicketPriceCalculator calculator; //SUT
@Mock MovieTheaterService service;

@Test void calculatePrice_tooMuchWork() {
  calculator = new TicketPriceCalculator(service);
  UserBalance balance = new DummyBalance("1.0");
  BigDecimal amount = new BigDecimal("9.3"));

    BigDecimal result = calculator.calculatePrice(balance, amount);

    assertThat(result, is(new BigDecimal("8.3"));
}
Digging into Collaborators,
more flavours
Flavour: "Context", "Container"...
class MovieTheaterService {

    void processOrder(UserContext context) {
      User user = context.getUser();
      Order order = context.getOrders().byUser(user).now();
      order.process();
    }
}
Flavour: "Context", "Container"...
class MovieTheaterService {

    void processOrder(UserContext context) {
      User user = context.getUser();
      Order order = context.getOrders().byUser(user).now();
      order.process();
    }
}
Flavour: "Context", "Container"...
class MovieTheaterService {

    void processOrder(UserContext context) {
      User user = context.getUser();
      Order order = context.getOrders().byUser(user).now();
      order.process();
    }

    // Test? Create a UserContext with ton of mocks and stuff
}
Flavour: "Context", "Container"...
class MovieTheaterService {

    void processOrder(UserContext context) {
      User user = context.getUser();
      Order order = context.getOrders().byUser(user).now();
      order.process();
    }

    // Test? Create a UserContext with ton of mocks and stuff
}
Fix: "Context", "Container"...
class MovieTheaterService {

    void processOrder(User user, Order order) {
      order.process();
    }

    // Test? Sure! You got everything you need in place.
}
Warning signs: Digging into Collaborators

Objects to use other objects, not themself.
Having to create mocks that return other mocks
Law of Demeter everywhere
Seeing more than one period (.) in a method
chaining. Going deep in the object graph:
  mgs.getSolid().findOcelot().now()
Exception: DSLs
Suspicious names
 Context, Environment, Container...
Smell: Global state and Singletons
Flavour: They are liars!
@Test void chargeCreditCard() { // Example: @mhevery
  CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009);
  assertThat(cc.charge(30.0), is(true));
}
Flavour: They are liars!
@Test void chargeCreditCard() {
  CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009);
  assertThat(cc.charge(30.0), is(true));

 // Fails at runtime:
 // java.lang.NullPointerExpection
}
Flavour: They are liars!
@Test void chargeCreditCard() {
  CreditCardProcessor.init();
  CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009);
  assertThat(cc.charge(30.0), is(true));
}
Flavour: They are liars!
@Test void chargeCreditCard() {
  CreditCardProcessor.init();
  CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009);
  assertThat(cc.charge(30.0), is(true));

 // Argh! This is getting awkward
 // java.lang.NullPointerExpection
}
Flavour: They are liars!
@Test void chargeCreditCard() {
  CreditCardProcessor.init();
  OfflineQueue.start();
  CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009);
  assertThat(cc.charge(30.0), is(true));
}
Flavour: They are liars!
@Test void chargeCreditCard() {
  CreditCardProcessor.init();
  OfflineQueue.start();
  CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009);
  assertThat(cc.charge(30.0), is(true));

 // Are you kidding?
 // java.lang.NullPointerExpection
}
Flavour: They are liars!
@Test void chargeCreditCard() {
  Database.connect("hsqldb");
  CreditCardProcessor.init();
  OfflineQueue.start();
  CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009);
  assertThat(cc.charge(30.0), is(true));
}
Flavour: They are liars!
@Test void chargeCreditCard() {
  Database.connect("hsqldb"); // Global State
  CreditCardProcessor.init(); // Global State
  OfflineQueue.start(); // Global State
  CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009);
  assertThat(cc.charge(30.0), is(true));

    // How do we know this? Sure it's documented somewhere... right?
}
How do you provide global variables in languages
without global variables?


"Don't. Your programs will
thank you for taking the
time to think about design
instead."
                          -- Kent Beck,
                             JUnit and TDD creator
Fix: They are liars!
Fix: They are liars!
Dependency Injection
Fix: They are liars!
Dependency Injection
Dependency Injection
Fix: They are liars!
Dependency Injection
Dependency Injection
Dependency Injection
Fix: They are liars!
Dependency Injection
Dependency Injection
Dependency Injection
Dependency Injection
Fix: They are liars!
@Test void chargeCreditCard() {
  Database db = mock(Database.class);
  Queue queue = new OfflineQueue(db);
  CreditCardProcessor ccProc = new CreditCardProcessor(queue);
  CreditCard cc = new CreditCard(ccProc, "9999 0000 7777");
  cc.charge(30.0);
}
Fix: They are liars!
@Test void chargeCreditCard() {
  Database db = mock(Database.class);
  Queue queue = new OfflineQueue(db);
  CreditCardProcessor ccProc = new CreditCardProcessor(queue);
  CreditCard cc = new CreditCard(ccProc, "9999 0000 7777");
  cc.charge(30.0);
}
Fix: They are liars!
@Test void chargeCreditCard() {
  CreditCardProcessor ccProc = mock(CreditCardProcessor.class);
  CreditCard cc = new CreditCard(ccProc, "9999 0000 7777");
  cc.charge(30.0);
}
About Singletons

Singletons and JVM Singletons
Gang of four, static instance field.
Best known as an Anti-pattern.


But there's nothing wrong about having one
instance of an Object
Application Singleton
Managed by someone, eg: Guice
@Singleton scope
About Global State

Global state is Evil
Dirty design, enables Action at a distance (anti-pattern),
extremely-hard-to-test, etc.


Caveat: When it's ok?
Primitive or immutable constant reference
  static final String DEVFEST = "Devfest rocks"
When information only travels one way
 org.slf4j.Logger // but hard to test
Warning signs: Global State and Singletons

Using Singletons
Static fields or static methods
 Don't confuse with helper or factory methods
Static initialization block
 class App {
   static {
     MutableObject object = Registry.find();
   }
 }
Service Locators
Smell: Class does too much
Smell: Class does too much, aka
Kitchen Sink
Smell: Class does too much, aka
Kitchen Sink
Dumping Ground
Smell: Class does too much, aka
Kitchen Sink
Dumping Ground
This Class does this AND that AND ...
Smell: Class does too much, aka
Kitchen Sink
Dumping Ground
This Class does this AND that AND ...
God Class
Smell: Class does too much, aka
Kitchen Sink
Dumping Ground
This Class does this AND that AND ...
God Class
Quijote
Smell: Class does too much, aka
Kitchen Sink
Dumping Ground
This Class does this AND that AND ...
God Class
Quijote
"You can look at everything except this
 Class"
Smell: Class does too much
interface MovieTheater {

    void open();

    void addShowtime(Showtime showtime);

    Set<Showtime> getShowtimes();

    void purchaseTicket(Buyer buyer, Movie movie);

    UserBalance findUserBalance(User balance);

    void processOrder(Order order);

    // ...
}
Smell: Class does too much
interface MovieTheater {

    void open();

    void addShowtime(Showtime showtime);

    Set<Showtime> getShowtimes();

    void purchaseTicket(Buyer buyer, Movie movie);

    UserBalance findUserBalance(User balance);

    void processOrder(Order order);

    // ...
}
Fix: Class does too much
interface MovieTheater {
  void open();

    void addShowtime(Showtime showtime);

    Set<Showtime> getShowtimes();
}

interface BillingService {
  void purchaseTicket(Buyer buyer, Movie movie);

    UserBalance findUserBalance(User balance);

    void processOrder(Order order);
}
Warning signs: Class does too much

Descriptive names for this smell
Tiny scroll bar
Many fields, many methods
 Use Sonar and LCOM4 (Lack of Cohesion) to check this
Many collaborators
Just don't getting the Class
Dependency Injection enables
you to write testable code
Deep synergies between
testable code and good design
                     -- Michael Feathers
Maintainable code
Much more Guice!
JSR330
javax.inject -- Google + Spring effort
Roboguice
Android, @InjectView, @InjectResource
Dagger
From Square, original Guice committers,
built on JSR330, pretty exciting!
References
Writing testable code Miško Hevery
Working effectively with legacy code Michael Feathers

The testability Explorer blog Blog, Miško Hevery
Dependency Injection Book, Dhanji R. Prasanna
Test Driven - Practical TDD for Java devs Book, Lasse Koskela (2007)
Effective Unit Testing - For Java devs Book, Lasse Koskela (2012)
xUnit Test Patterns Book, Gerard Meszaros
Painless Testing Slides, in Java or Python. Johannes Seitz
Thanks!

slideshare.net/giro9    jordi@donky.org
                                @jordi9
Q&A

      jordi@donky.org
              @jordi9

More Related Content

What's hot

Unit testing en iOS @ MobileCon Galicia
Unit testing en iOS @ MobileCon GaliciaUnit testing en iOS @ MobileCon Galicia
Unit testing en iOS @ MobileCon GaliciaRobot Media
 
Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Danny Preussler
 
Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011Anton Arhipov
 
Con-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistCon-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistAnton Arhipov
 
Demystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and ToothpickDemystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and ToothpickDanny Preussler
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for ProgrammersDavid Rodenas
 
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)Danny Preussler
 
Unit testing with PHPUnit - there's life outside of TDD
Unit testing with PHPUnit - there's life outside of TDDUnit testing with PHPUnit - there's life outside of TDD
Unit testing with PHPUnit - there's life outside of TDDPaweł Michalik
 
Keep your repo clean
Keep your repo cleanKeep your repo clean
Keep your repo cleanHector Canto
 
Introduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitIntroduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitMichelangelo van Dam
 
Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++Sergey Platonov
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockRobot Media
 
Unit Testing: Special Cases
Unit Testing: Special CasesUnit Testing: Special Cases
Unit Testing: Special CasesCiklum Ukraine
 
Going On with the Check of Geant4
Going On with the Check of Geant4Going On with the Check of Geant4
Going On with the Check of Geant4Andrey Karpov
 
Metaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common LispMetaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common LispDamien Cassou
 
Uazaa uma-farsa-parte 2
Uazaa uma-farsa-parte 2Uazaa uma-farsa-parte 2
Uazaa uma-farsa-parte 2devninjabr
 
Effective testing with pytest
Effective testing with pytestEffective testing with pytest
Effective testing with pytestHector Canto
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicGraham Dumpleton
 
Functional Reactive Programming on Android
Functional Reactive Programming on AndroidFunctional Reactive Programming on Android
Functional Reactive Programming on AndroidSam Lee
 

What's hot (20)

Unit testing en iOS @ MobileCon Galicia
Unit testing en iOS @ MobileCon GaliciaUnit testing en iOS @ MobileCon Galicia
Unit testing en iOS @ MobileCon Galicia
 
Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016
 
Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011
 
Con-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With JavassistCon-FESS 2015 - Having Fun With Javassist
Con-FESS 2015 - Having Fun With Javassist
 
Getting Testy With Perl6
Getting Testy With Perl6Getting Testy With Perl6
Getting Testy With Perl6
 
Demystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and ToothpickDemystifying dependency Injection: Dagger and Toothpick
Demystifying dependency Injection: Dagger and Toothpick
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
 
Unit testing with PHPUnit - there's life outside of TDD
Unit testing with PHPUnit - there's life outside of TDDUnit testing with PHPUnit - there's life outside of TDD
Unit testing with PHPUnit - there's life outside of TDD
 
Keep your repo clean
Keep your repo cleanKeep your repo clean
Keep your repo clean
 
Introduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitIntroduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnit
 
Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
 
Unit Testing: Special Cases
Unit Testing: Special CasesUnit Testing: Special Cases
Unit Testing: Special Cases
 
Going On with the Check of Geant4
Going On with the Check of Geant4Going On with the Check of Geant4
Going On with the Check of Geant4
 
Metaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common LispMetaprogramming and Reflection in Common Lisp
Metaprogramming and Reflection in Common Lisp
 
Uazaa uma-farsa-parte 2
Uazaa uma-farsa-parte 2Uazaa uma-farsa-parte 2
Uazaa uma-farsa-parte 2
 
Effective testing with pytest
Effective testing with pytestEffective testing with pytest
Effective testing with pytest
 
DjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New RelicDjangoCon US 2011 - Monkeying around at New Relic
DjangoCon US 2011 - Monkeying around at New Relic
 
Functional Reactive Programming on Android
Functional Reactive Programming on AndroidFunctional Reactive Programming on Android
Functional Reactive Programming on Android
 

Viewers also liked

Google Guice presentation at Montreal JUG - October 2010
Google Guice presentation at Montreal JUG - October 2010Google Guice presentation at Montreal JUG - October 2010
Google Guice presentation at Montreal JUG - October 2010Mathieu Carbou
 
BeScala - Scala Guice
BeScala -  Scala GuiceBeScala -  Scala Guice
BeScala - Scala GuiceBeScala
 
Guice - dependency injection framework
Guice - dependency injection frameworkGuice - dependency injection framework
Guice - dependency injection frameworkEvgeny Barabanov
 
Ozma: Extending Scala with Oz concurrency
Ozma: Extending Scala with Oz concurrencyOzma: Extending Scala with Oz concurrency
Ozma: Extending Scala with Oz concurrencyBeScala
 
ScalaCheck Cookbook v1.0
ScalaCheck Cookbook v1.0ScalaCheck Cookbook v1.0
ScalaCheck Cookbook v1.0Oscar Renalias
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google GuiceKnoldus Inc.
 
5-minute intro to property-based testing in Python with hypothesis
5-minute intro to property-based testing in Python with hypothesis5-minute intro to property-based testing in Python with hypothesis
5-minute intro to property-based testing in Python with hypothesisFranklin Chen
 

Viewers also liked (9)

Google Guice presentation at Montreal JUG - October 2010
Google Guice presentation at Montreal JUG - October 2010Google Guice presentation at Montreal JUG - October 2010
Google Guice presentation at Montreal JUG - October 2010
 
Google Guice
Google GuiceGoogle Guice
Google Guice
 
BeScala - Scala Guice
BeScala -  Scala GuiceBeScala -  Scala Guice
BeScala - Scala Guice
 
Guice - dependency injection framework
Guice - dependency injection frameworkGuice - dependency injection framework
Guice - dependency injection framework
 
Ozma: Extending Scala with Oz concurrency
Ozma: Extending Scala with Oz concurrencyOzma: Extending Scala with Oz concurrency
Ozma: Extending Scala with Oz concurrency
 
ScalaCheck Cookbook v1.0
ScalaCheck Cookbook v1.0ScalaCheck Cookbook v1.0
ScalaCheck Cookbook v1.0
 
Eway google-guice presentation
Eway google-guice presentationEway google-guice presentation
Eway google-guice presentation
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google Guice
 
5-minute intro to property-based testing in Python with hypothesis
5-minute intro to property-based testing in Python with hypothesis5-minute intro to property-based testing in Python with hypothesis
5-minute intro to property-based testing in Python with hypothesis
 

Similar to Clean code via dependency injection + guice

Java EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJava EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJiayun Zhou
 
Introduction To Spring
Introduction To SpringIntroduction To Spring
Introduction To SpringIlio Catallo
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHPKacper Gunia
 
Curso de Node.js e MongoDB - 16
Curso de Node.js e MongoDB - 16Curso de Node.js e MongoDB - 16
Curso de Node.js e MongoDB - 16Luiz Duarte
 
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...DicodingEvent
 
Enterprise Guice 20090217 Bejug
Enterprise Guice 20090217 BejugEnterprise Guice 20090217 Bejug
Enterprise Guice 20090217 Bejugrobbiev
 
Building a Native Camera Access Library - Part I.pdf
Building a Native Camera Access Library - Part I.pdfBuilding a Native Camera Access Library - Part I.pdf
Building a Native Camera Access Library - Part I.pdfShaiAlmog1
 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2Kacper Gunia
 
Maintaining a dependency graph with weaver
Maintaining a dependency graph with weaverMaintaining a dependency graph with weaver
Maintaining a dependency graph with weaverScribd
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfShaiAlmog1
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionChristian Panadero
 
castle-windsor-ioc-demo
castle-windsor-ioc-democastle-windsor-ioc-demo
castle-windsor-ioc-demoAmir Barylko
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xTatsuya Maki
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleThierry Wasylczenko
 
Making React Native UI Components with Swift
Making React Native UI Components with SwiftMaking React Native UI Components with Swift
Making React Native UI Components with SwiftRay Deck
 
Advanced AV Foundation (CocoaConf, Aug '11)
Advanced AV Foundation (CocoaConf, Aug '11)Advanced AV Foundation (CocoaConf, Aug '11)
Advanced AV Foundation (CocoaConf, Aug '11)Chris Adamson
 

Similar to Clean code via dependency injection + guice (20)

Java EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSFJava EE 6 CDI Integrates with Spring & JSF
Java EE 6 CDI Integrates with Spring & JSF
 
Introduction To Spring
Introduction To SpringIntroduction To Spring
Introduction To Spring
 
Android workshop
Android workshopAndroid workshop
Android workshop
 
Kotlin After 9 Months
Kotlin After 9 MonthsKotlin After 9 Months
Kotlin After 9 Months
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHP
 
Curso de Node.js e MongoDB - 16
Curso de Node.js e MongoDB - 16Curso de Node.js e MongoDB - 16
Curso de Node.js e MongoDB - 16
 
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
Dicoding Developer Coaching #30: Android | Mengenal Macam-Macam Software Desi...
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
Enterprise Guice 20090217 Bejug
Enterprise Guice 20090217 BejugEnterprise Guice 20090217 Bejug
Enterprise Guice 20090217 Bejug
 
Building a Native Camera Access Library - Part I.pdf
Building a Native Camera Access Library - Part I.pdfBuilding a Native Camera Access Library - Part I.pdf
Building a Native Camera Access Library - Part I.pdf
 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2
 
Maintaining a dependency graph with weaver
Maintaining a dependency graph with weaverMaintaining a dependency graph with weaver
Maintaining a dependency graph with weaver
 
create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
 
castle-windsor-ioc-demo
castle-windsor-ioc-democastle-windsor-ioc-demo
castle-windsor-ioc-demo
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.x
 
Hidden rocks in Oracle ADF
Hidden rocks in Oracle ADFHidden rocks in Oracle ADF
Hidden rocks in Oracle ADF
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
Making React Native UI Components with Swift
Making React Native UI Components with SwiftMaking React Native UI Components with Swift
Making React Native UI Components with Swift
 
Advanced AV Foundation (CocoaConf, Aug '11)
Advanced AV Foundation (CocoaConf, Aug '11)Advanced AV Foundation (CocoaConf, Aug '11)
Advanced AV Foundation (CocoaConf, Aug '11)
 

More from Jordi Gerona

Netty from the trenches
Netty from the trenchesNetty from the trenches
Netty from the trenchesJordi Gerona
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidJordi Gerona
 
Unit Testing - Trovit
Unit Testing - TrovitUnit Testing - Trovit
Unit Testing - TrovitJordi Gerona
 
Mitos y otras criaturas startuperas (webbar)
Mitos y otras criaturas startuperas (webbar)Mitos y otras criaturas startuperas (webbar)
Mitos y otras criaturas startuperas (webbar)Jordi Gerona
 
Unit Testing - GTUG
Unit Testing - GTUGUnit Testing - GTUG
Unit Testing - GTUGJordi Gerona
 
Dependency Injection con Guice - GTUG
Dependency Injection con Guice - GTUGDependency Injection con Guice - GTUG
Dependency Injection con Guice - GTUGJordi Gerona
 

More from Jordi Gerona (7)

Netty from the trenches
Netty from the trenchesNetty from the trenches
Netty from the trenches
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & Android
 
Unit Testing - Trovit
Unit Testing - TrovitUnit Testing - Trovit
Unit Testing - Trovit
 
Mitos y otras criaturas startuperas (webbar)
Mitos y otras criaturas startuperas (webbar)Mitos y otras criaturas startuperas (webbar)
Mitos y otras criaturas startuperas (webbar)
 
Mercurial
MercurialMercurial
Mercurial
 
Unit Testing - GTUG
Unit Testing - GTUGUnit Testing - GTUG
Unit Testing - GTUG
 
Dependency Injection con Guice - GTUG
Dependency Injection con Guice - GTUGDependency Injection con Guice - GTUG
Dependency Injection con Guice - GTUG
 

Recently uploaded

Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfjimielynbastida
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 

Recently uploaded (20)

Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 

Clean code via dependency injection + guice

  • 1. Clean code via Dependency Injection + Guice @jordi9 bit.ly/devfest12cleancode 9 noviembre 2012
  • 3. About you Gang of Four? Legacy Code? Dependency Injection? Monkey patching? Monkey testing? Unit testing? TDD / BDD? Agile? XP? Scrum what?
  • 4. S.O.L.I.D. Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation principle Dependency inversion principle
  • 5. Legacy code is code without test
  • 6. F.I.R.S.T. Fast Run hundreds or thousands per second Isolated Failure reasons become obvious Reliable Run repeatedly in any order, any time Self-validating No manual evaluation required Timely Written before the code
  • 7. Write some code, kill technical debt (or not)
  • 8. Showtime! class Showtimes { MovieRepository repository; Showtimes() { repository = MovieRepositoryFactory.getInstance(); } Set<Movie> findMovies(City city) { return repository.findByCity(city); } }
  • 9. Smell: Constructor does real work class Showtimes { MovieRepository repository; Showtimes() { repository = MovieRepositoryFactory.getInstance(); } Set<Movie> findMovies(City city) { return repository.findByCity(city); } }
  • 10. Smell: Constructor does real work class Showtimes { MovieRepository repository; Showtimes() { repository = MovieRepositoryFactory.getInstance(); } Set<Movie> findMovies(City city) { return repository.findByCity(city); } }
  • 11. Smell: Constructor does real work class Showtimes { MovieRepository repository; Showtimes() { repository = MovieRepositoryFactory.getInstance(); } Set<Movie> findMovies(City city) { return repository.findByCity(city); } }
  • 12. Factory Pattern, boilerplate public class MovieRepositoryFactory { static class MovieRepositoryHolder { static MovieRepository instance = new MovieRepositoryImpl(); } public static MovieRepository getInstance() { return MovieRepositoryHolder.instance; } static void setInstance(MovieRepository mock) { MovieRepositoryHolder.instance = mock; } }
  • 13. Factory Pattern, boilerplate public class MovieRepositoryFactory { static class MovieRepositoryHolder { static MovieRepository instance = new MovieRepositoryImpl(); } public static MovieRepository getInstance() { return MovieRepositoryHolder.instance; } static void setInstance(MovieRepository mock) { MovieRepositoryHolder.instance = mock; } }
  • 14. Factory Pattern, boilerplate public class MovieRepositoryFactory { static class MovieRepositoryHolder { static MovieRepository instance = new MovieRepositoryImpl(); } public static MovieRepository getInstance() { return MovieRepositoryHolder.instance; } static void setInstance(MovieRepository mock) { MovieRepositoryHolder.instance = mock; } }
  • 15. Factory Pattern, boilerplate public class MovieRepositoryFactory { static class MovieRepositoryHolder { static MovieRepository instance = new MovieRepositoryImpl(); } public static MovieRepository getInstance() { return MovieRepositoryHolder.instance; } static void setInstance(MovieRepository mock) { MovieRepositoryHolder.instance = mock; } }
  • 16. Factory Pattern, boilerplate public class MovieRepositoryFactory { static class MovieRepositoryHolder { static MovieRepository instance = new MovieRepositoryImpl(); } public static MovieRepository getInstance() { return MovieRepositoryHolder.instance; } static void setInstance(MovieRepository mock) { MovieRepositoryHolder.instance = mock; } }
  • 17. Factory Pattern, boilerplate public class MovieRepositoryFactory { static class MovieRepositoryHolder { static MovieRepository instance = new MovieRepositoryImpl(); } public static MovieRepository getInstance() { return MovieRepositoryHolder.instance; } static void setInstance(MovieRepository mock) { MovieRepositoryHolder.instance = mock; } }
  • 18. Hard to test @Test void findMovies_cantTestYouDude() { Showtimes showtimes = new Showtimes(); // FRAK! // No database setup... I'm stuck with my collaborators // Can't really change it... Will it run in my // partners computer? }
  • 20. Fix: Constructor does real work class Showtimes { MovieRepository repository; Showtimes(MovieRepository repository) { this.repository = repository; } Set<Movie> findMovies(City city) { return repository.findByCity(city); } }
  • 21. Fix: Constructor does real work class Showtimes { // Hollywood principle: "Don't call us, we'll call you" MovieRepository repository; Showtimes(MovieRepository repository) { this.repository = repository; } Set<Movie> findMovies(City city) { return repository.findByCity(city); } }
  • 22. Fix: Constructor does real work class Showtimes { // Hollywood principle: "Don't call us, we'll call you" MovieRepository repository; @Inject Showtimes(MovieRepository repository) { this.repository = repository; } Set<Movie> findMovies(City city) { return repository.findByCity(city); } }
  • 23. Fix: MovieRepository creation? class App { public static void main(String[] args) { // Manual Dependency Injection... but much more // boilerplate! // Maybe some <init> method... but that's why // constructors exist right? // Some container injection... mmm... Spring, Pico? // Or better, Guice time! } }
  • 24. Fix: MovieRepository creation class App { public static void main(String[] args) { Injector injector = Guice.createInjector( new AbstractModule() { @Override void configure() { bind(MovieRepository.class) .to(JpaMovieRepository.class); } }); injector.getInstance(Showtimes.class).findMovies(bcn); } }
  • 25. Fix: MovieRepository creation class App { public static void main(String[] args) { Injector injector = Guice.createInjector( new AbstractModule() { @Override void configure() { bind(MovieRepository.class) .to(JpaMovieRepository.class); } }); injector.getInstance(Showtimes.class).findMovies(bcn); } }
  • 26. Fix: MovieRepository creation class App { public static void main(String[] args) { Injector injector = Guice.createInjector( new AbstractModule() { @Override void configure() { bind(MovieRepository.class) .to(JpaMovieRepository.class); } }); // Injection is VIRAL! Avoid at all cost using the // Injector in more than one place (aka Service Locator) injector.getInstance(Showtimes.class).findMovies(bcn); } }
  • 27. Fix: Testable and flexible design Showtimes showtimes; @Mock MovieRepository repository; @Test void findMovies_easyNow() { showtimes = new Showtimes(repository); given(repository.findByCity(bcn)) .willReturn(ImmutableSet.of(looper)); Set<Movie> movies = showtimes.findMovies(bcn); assertThat(movies, hasItem(looper)); }
  • 28. Fix: Testable and flexible design Showtimes showtimes; //SUT @Mock MovieRepository repository; @Test void findMovies_easyNow() { showtimes = new Showtimes(repository); given(repository.findByCity(bcn)) .willReturn(ImmutableSet.of(looper)); Set<Movie> movies = showtimes.findMovies(bcn); assertThat(movies, hasItem(looper)); }
  • 29. Fix: Testable and flexible design Showtimes showtimes; //SUT @Mock MovieRepository repository; // <3 Mockito, BDD @Test void findMovies_easyNow() { showtimes = new Showtimes(repository); //given given(repository.findByCity(bcn)) .willReturn(ImmutableSet.of(looper)); //when Set<Movie> movies = showtimes.findMovies(bcn); //then assertThat(movies, hasItem(looper)); }
  • 30. Fix: Testable and flexible design Showtimes showtimes; //SUT @Mock MovieRepository repository; // <3 Mockito, BDD @Test void findMovies_easyNow() { showtimes = new Showtimes(repository); //given given(repository.findByCity(bcn)) .willReturn(ImmutableSet.of(looper)); //when Set<Movie> movies = showtimes.findMovies(bcn); //then assertThat(movies, hasItem(looper)); // <3 Hamcrest }
  • 31. Fix: Testable and flexible design Showtimes showtimes; //SUT @Mock MovieRepository repository; // <3 Mockito, BDD @Test void findMovies_easyNow() { showtimes = new Showtimes(repository); //given given(repository.findByCity(bcn)) .willReturn(ImmutableSet.of(looper)); // <3 Guava //when Set<Movie> movies = showtimes.findMovies(bcn); //then assertThat(movies, hasItem(looper)); // <3 Hamcrest }
  • 32. Constructor does real work, more flavours
  • 33. Flavour: Partial objects, Law of Demeter class Ratings { User user; Ratings(AccountManager manager) { user = manager.getLoggedUser(); user.setQueue(new ItTakesForeverToBuildOSSQueue()); } }
  • 34. Flavour: Partial objects, Law of Demeter class Ratings { User user; Ratings(AccountManager manager) { user = manager.getLoggedUser(); user.setQueue(new ItTakesForeverToBuildOSSQueue()); } // Test? Slow, really slow // We don't use AccountManager anywhere else }
  • 35. Fix: Partial objects, Law of Demeter class Ratings { User user; @Inject Ratings(User user) { this.user = user; } }
  • 36. Fix: Partial objects, Law of Demeter class Ratings { User user; // How do we inject this User like we need it? // Where's the Queue? @Inject Ratings(User user) { this.user = user; } }
  • 37. Fix: Partial objects, Law of Demeter @Provides User providesUser(AccountManager manager, Queue queue) { User user = manager.getLoggedUser(); user.setQueue(queue); return user; } @Provides @Singleton Queue providesLongRunningQueue() { return new ItTakesForeverToBuildOSSQueue(); }
  • 38. Fix: Partial objects, Law of Demeter @Provides User providesUser(AccountManager manager, Queue queue) { User user = manager.getLoggedUser(); user.setQueue(queue); return user; } @Provides @Singleton Queue providesLongRunningQueue() { return new ItTakesForeverToBuildOSSQueue(); }
  • 39. Fix: Partial objects, Law of Demeter @Provides User providesUser(AccountManager manager, Queue queue) { User user = manager.getLoggedUser(); user.setQueue(queue); return user; } @Provides @Singleton // no JVM Singleton, yay! Queue providesLongRunningQueue() { return new ItTakesForeverToBuildOSSQueue(); }
  • 40. Fix: Partial objects, Law of Demeter @Provides User providesUser(AccountManager manager, Queue queue) { User user = manager.getLoggedUser(); user.setQueue(queue); return user; } @Provides @Singleton // no JVM Singleton, yay! Queue providesLongRunningQueue() { return new ItTakesForeverToBuildOSSQueue(); } // Provider methods should be inside a Module
  • 41. Test: Partial objects, Law of Demeter Ratings ratings; //SUT @Test void ratings_findAverage() { ratings = new Ratings(new DummyUser()); // Easy to test now, we can have a mock or test-double // and check everything about Ratings. We don't care // about collaborators. }
  • 42. Warning signs: Constructor does real work New keyword in constructor or fields Static method calls Anything more than field assignments Object not fully initialized after constructor Control flow
  • 43. Smell: Digging into Collaborators
  • 44. Flavour: Digging around class TicketPriceCalculator { MovieTheaterService service; TicketPriceCalculator(MovieTheaterService service) { this.service = service; } BigDecimal calculatePrice(User user, Invoice invoice) { UserBalance balance = user.getBalance(); BigDecimal amount = invoice.getSubtotal(); return service.calculateTotal(balance, amount); } }
  • 45. Flavour: Digging around class TicketPriceCalculator { MovieTheaterService service; TicketPriceCalculator(MovieTheaterService service) { this.service = service; } BigDecimal calculatePrice(User user, Invoice invoice) { UserBalance balance = user.getBalance(); BigDecimal amount = invoice.getSubtotal(); return service.calculateTotal(balance, amount); } }
  • 46. Hard to test? Digging around TicketPriceCalculator calculator; //SUT @Mock MovieTheaterService service; @Test void calculatePrice_tooMuchWork() { calculator = new TicketPriceCalculator(service); given(user.getBalance()).willReturn(new DummyBalance()); given(invoice.getSubtotal()).willReturn(new BigDecimal("9.3")); BigDecimal result = calculator.calculatePrice(balance, invoice); assertThat(result, is(new BigDecimal("8.3")); }
  • 47. Hard to test? Digging around TicketPriceCalculator calculator; //SUT @Mock MovieTheaterService service; @Test void calculatePrice_tooMuchWork() { calculator = new TicketPriceCalculator(service); given(user.getBalance()).willReturn(new DummyBalance()); given(invoice.getSubtotal()).willReturn(new BigDecimal("9.3")); BigDecimal result = calculator.calculatePrice(balance, invoice); assertThat(result, is(new BigDecimal("8.3")); }
  • 48. Flavour: Digging around class TicketPriceCalculator { MovieTheaterService service; TicketPriceCalculator(MovieTheaterService service) { this.service = service; } // Deceitful API, Law of Demeter BigDecimal calculatePrice(User user, Invoice invoice) { UserBalance balance = user.getBalance(); BigDecimal amount = invoice.getSubtotal(); return service.calculateTotal(balance, amount); } }
  • 49. Flavour: Digging around class TicketPriceCalculator { MovieTheaterService service; TicketPriceCalculator(MovieTheaterService service) { this.service = service; } // Problem? Imagine this in a big application, your code // will be much more complicated than you (and your team) need BigDecimal calculatePrice(User user, Invoice invoice) { UserBalance balance = user.getBalance(); BigDecimal amount = invoice.getSubtotal(); return service.calculateTotal(balance, amount); } }
  • 50. Fix: Digging around class TicketPriceCalculator { MovieTheaterService service; TicketPriceCalculator(MovieTheaterService service) { this.service = service; } // Cleaner API, forget about "Middle men" class BigDecimal calculatePrice(UserBalance balance, BigDecimal am) { return service.calculateTotal(balance, am); } }
  • 51. Fix: Digging around TicketPriceCalculator calculator; //SUT @Mock MovieTheaterService service; @Test void calculatePrice_tooMuchWork() { calculator = new TicketPriceCalculator(service); UserBalance balance = new DummyBalance("1.0"); BigDecimal amount = new BigDecimal("9.3")); BigDecimal result = calculator.calculatePrice(balance, amount); assertThat(result, is(new BigDecimal("8.3")); }
  • 53. Flavour: "Context", "Container"... class MovieTheaterService { void processOrder(UserContext context) { User user = context.getUser(); Order order = context.getOrders().byUser(user).now(); order.process(); } }
  • 54. Flavour: "Context", "Container"... class MovieTheaterService { void processOrder(UserContext context) { User user = context.getUser(); Order order = context.getOrders().byUser(user).now(); order.process(); } }
  • 55. Flavour: "Context", "Container"... class MovieTheaterService { void processOrder(UserContext context) { User user = context.getUser(); Order order = context.getOrders().byUser(user).now(); order.process(); } // Test? Create a UserContext with ton of mocks and stuff }
  • 56. Flavour: "Context", "Container"... class MovieTheaterService { void processOrder(UserContext context) { User user = context.getUser(); Order order = context.getOrders().byUser(user).now(); order.process(); } // Test? Create a UserContext with ton of mocks and stuff }
  • 57. Fix: "Context", "Container"... class MovieTheaterService { void processOrder(User user, Order order) { order.process(); } // Test? Sure! You got everything you need in place. }
  • 58. Warning signs: Digging into Collaborators Objects to use other objects, not themself. Having to create mocks that return other mocks Law of Demeter everywhere Seeing more than one period (.) in a method chaining. Going deep in the object graph: mgs.getSolid().findOcelot().now() Exception: DSLs Suspicious names Context, Environment, Container...
  • 59. Smell: Global state and Singletons
  • 60. Flavour: They are liars! @Test void chargeCreditCard() { // Example: @mhevery CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009); assertThat(cc.charge(30.0), is(true)); }
  • 61. Flavour: They are liars! @Test void chargeCreditCard() { CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009); assertThat(cc.charge(30.0), is(true)); // Fails at runtime: // java.lang.NullPointerExpection }
  • 62. Flavour: They are liars! @Test void chargeCreditCard() { CreditCardProcessor.init(); CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009); assertThat(cc.charge(30.0), is(true)); }
  • 63. Flavour: They are liars! @Test void chargeCreditCard() { CreditCardProcessor.init(); CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009); assertThat(cc.charge(30.0), is(true)); // Argh! This is getting awkward // java.lang.NullPointerExpection }
  • 64. Flavour: They are liars! @Test void chargeCreditCard() { CreditCardProcessor.init(); OfflineQueue.start(); CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009); assertThat(cc.charge(30.0), is(true)); }
  • 65. Flavour: They are liars! @Test void chargeCreditCard() { CreditCardProcessor.init(); OfflineQueue.start(); CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009); assertThat(cc.charge(30.0), is(true)); // Are you kidding? // java.lang.NullPointerExpection }
  • 66. Flavour: They are liars! @Test void chargeCreditCard() { Database.connect("hsqldb"); CreditCardProcessor.init(); OfflineQueue.start(); CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009); assertThat(cc.charge(30.0), is(true)); }
  • 67. Flavour: They are liars! @Test void chargeCreditCard() { Database.connect("hsqldb"); // Global State CreditCardProcessor.init(); // Global State OfflineQueue.start(); // Global State CreditCard cc = new CreditCard("9999 0000 7777", 5, 2009); assertThat(cc.charge(30.0), is(true)); // How do we know this? Sure it's documented somewhere... right? }
  • 68. How do you provide global variables in languages without global variables? "Don't. Your programs will thank you for taking the time to think about design instead." -- Kent Beck, JUnit and TDD creator
  • 69. Fix: They are liars!
  • 70. Fix: They are liars! Dependency Injection
  • 71. Fix: They are liars! Dependency Injection Dependency Injection
  • 72. Fix: They are liars! Dependency Injection Dependency Injection Dependency Injection
  • 73. Fix: They are liars! Dependency Injection Dependency Injection Dependency Injection Dependency Injection
  • 74. Fix: They are liars! @Test void chargeCreditCard() { Database db = mock(Database.class); Queue queue = new OfflineQueue(db); CreditCardProcessor ccProc = new CreditCardProcessor(queue); CreditCard cc = new CreditCard(ccProc, "9999 0000 7777"); cc.charge(30.0); }
  • 75. Fix: They are liars! @Test void chargeCreditCard() { Database db = mock(Database.class); Queue queue = new OfflineQueue(db); CreditCardProcessor ccProc = new CreditCardProcessor(queue); CreditCard cc = new CreditCard(ccProc, "9999 0000 7777"); cc.charge(30.0); }
  • 76. Fix: They are liars! @Test void chargeCreditCard() { CreditCardProcessor ccProc = mock(CreditCardProcessor.class); CreditCard cc = new CreditCard(ccProc, "9999 0000 7777"); cc.charge(30.0); }
  • 77. About Singletons Singletons and JVM Singletons Gang of four, static instance field. Best known as an Anti-pattern. But there's nothing wrong about having one instance of an Object Application Singleton Managed by someone, eg: Guice @Singleton scope
  • 78. About Global State Global state is Evil Dirty design, enables Action at a distance (anti-pattern), extremely-hard-to-test, etc. Caveat: When it's ok? Primitive or immutable constant reference static final String DEVFEST = "Devfest rocks" When information only travels one way org.slf4j.Logger // but hard to test
  • 79. Warning signs: Global State and Singletons Using Singletons Static fields or static methods Don't confuse with helper or factory methods Static initialization block class App { static { MutableObject object = Registry.find(); } } Service Locators
  • 80. Smell: Class does too much
  • 81. Smell: Class does too much, aka Kitchen Sink
  • 82. Smell: Class does too much, aka Kitchen Sink Dumping Ground
  • 83. Smell: Class does too much, aka Kitchen Sink Dumping Ground This Class does this AND that AND ...
  • 84. Smell: Class does too much, aka Kitchen Sink Dumping Ground This Class does this AND that AND ... God Class
  • 85. Smell: Class does too much, aka Kitchen Sink Dumping Ground This Class does this AND that AND ... God Class Quijote
  • 86. Smell: Class does too much, aka Kitchen Sink Dumping Ground This Class does this AND that AND ... God Class Quijote "You can look at everything except this Class"
  • 87. Smell: Class does too much interface MovieTheater { void open(); void addShowtime(Showtime showtime); Set<Showtime> getShowtimes(); void purchaseTicket(Buyer buyer, Movie movie); UserBalance findUserBalance(User balance); void processOrder(Order order); // ... }
  • 88. Smell: Class does too much interface MovieTheater { void open(); void addShowtime(Showtime showtime); Set<Showtime> getShowtimes(); void purchaseTicket(Buyer buyer, Movie movie); UserBalance findUserBalance(User balance); void processOrder(Order order); // ... }
  • 89. Fix: Class does too much interface MovieTheater { void open(); void addShowtime(Showtime showtime); Set<Showtime> getShowtimes(); } interface BillingService { void purchaseTicket(Buyer buyer, Movie movie); UserBalance findUserBalance(User balance); void processOrder(Order order); }
  • 90. Warning signs: Class does too much Descriptive names for this smell Tiny scroll bar Many fields, many methods Use Sonar and LCOM4 (Lack of Cohesion) to check this Many collaborators Just don't getting the Class
  • 91. Dependency Injection enables you to write testable code
  • 92. Deep synergies between testable code and good design -- Michael Feathers
  • 94. Much more Guice! JSR330 javax.inject -- Google + Spring effort Roboguice Android, @InjectView, @InjectResource Dagger From Square, original Guice committers, built on JSR330, pretty exciting!
  • 95. References Writing testable code Miško Hevery Working effectively with legacy code Michael Feathers The testability Explorer blog Blog, Miško Hevery Dependency Injection Book, Dhanji R. Prasanna Test Driven - Practical TDD for Java devs Book, Lasse Koskela (2007) Effective Unit Testing - For Java devs Book, Lasse Koskela (2012) xUnit Test Patterns Book, Gerard Meszaros Painless Testing Slides, in Java or Python. Johannes Seitz
  • 96. Thanks! slideshare.net/giro9 jordi@donky.org @jordi9
  • 97. Q&A jordi@donky.org @jordi9