Dependency injection when you only have one dependency JavaZone Johannes Brodwall, Recovering Spring User Steria Norway
Let’s get rid of dogmatic dependency injection
Does this look familiar?
Person- Controller Person- Controller- Impl Person- Service Person- ServiceImpl Person- Repository Impl Person- Repository Impl PersonDao Impl PersonDao Impl Session- Factory
Customer Invoice Order Product
No more: this.personService = new PersonServiceImpl(sessionFactory)
Instead:
private PersonService personService;
Why?
(dear God, why?!)
Testing
Multiple implementations
(Really?)
Configuration
(Often one)
Ordnung muss sein!
(Ordnung muss sein!) Hobgoblin of little minds - Ralph Waldo Emerson
Alternative
Session- Factory PersonController Service Repo sitory
public class PersonController { private PersonService public PersonController(SessionFactory sf) { this.personService = new PersonServiceImpl(sf); }
public class PersonController { private PersonService public PersonController(SessionFactory sf) { this.personService = new PersonServiceImpl(sf); } public class PersonServiceImpl implements … { private PersonRepository personRepo; public PersonServiceImpl(SessionFactory sf) { this.personRepo = new PersonRepositoryImpl(sf); }
public class PersonController { private PersonService public PersonController(SessionFactory sf) { this.personService = new PersonServiceImpl(sf); } public PersonControllerImpl(PersonService ps) { this.personService = ps; }
public class PersonController { private PersonService public PersonController(SessionFactory sf) { this.personService = new PersonServiceImpl(sf); } public PersonControllerImpl(PersonService ps) { this.personService = ps; } For Spring For mocking
SPRING! Session- Factory PersonController Service Repo sitory InvoiceController Repository FooServiceImpl ReportsController FooController
Look ma! No Spring!
Session- Factory PersonServlet Locator (singleton O_O) Locator (singleton O_O) ”Injected” by servlet
public class PersonController extends HttpServlet { private PersonService personService; public PersonController() { } public PersonController(PersonService personService) { this.personService = personService; public void init() throws ServletException { SessionFactory sf = HibernateLookup.getInstance(getServletContext()); this.personService = new PersonServiceImpl(sf); }
public class PersonController extends HttpServlet { private PersonService personService; public PersonController() { } public PersonController(PersonService personService) { this.personService = personService; public void init() throws ServletException { SessionFactory sf = HibernateLookup.getInstance(getServletContext()); this.personService = new PersonServiceImpl(sf); } For mocking Look, ma! No Spring!
Session- Factory PersonController Service Repo sitory InvoiceController Repository FooServiceImpl ReportsController FooController >
Bonus: Generic Repository
public interface Repository { T retrieve(Class type,Serializable id); Serializable save(Object object); List find(Specification spec); Transaction beginTransaction(); }
@RunWith(RepositoryTestRunner.class) public class PersonControllerTest { private Repository repository; private PersonController personController; public PersonControllerTest(Repository repo) { this.repository = repo; this.personController = new PersonController(repo); }
@Test public void should_show_person() { Person person = new Person(); Long id = (Long) repository.save(person); ModelAndView show = personController.show(id); assertEquals(person, show.getModel().get("person")); }
public class RepoTestRunner extends Suite { public RepoTestRunner(Class testClass) { super(testClass, createRunners(testClass)); } static List createRunners(Class testClass) { List runners = new ArrayList (); runners.add(testRunner(testClass, new HashMapRepository())); if (!isRunningInInfinitest()) { runners.add(testRunner(testClass, hibernateRepository())); } return runners; }
What Spring taught me
Be aware of dependencies!
Avoid differences between test and prod
Stay the heck away from frameworks!
Collapse service chains
Takk for meg!