Dependency injection in Scala

3,755 views

Published on

how to use Dependency injection in scala

Published in: Software, Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,755
On SlideShare
0
From Embeds
0
Number of Embeds
3,096
Actions
Shares
0
Downloads
18
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Dependency injection in Scala

  1. 1. Dependency InjectionDependency Injection Satendra Kumar Software Consultant, Knoldus Software LLP Satendra Kumar Software Consultant, Knoldus Software LLP
  2. 2. Topics CoveredTopics Covered What is dependency Injection Why should we use it Implementations Live Demo What is dependency Injection Why should we use it Implementations Live Demo
  3. 3. What is DI ● Dependency injection is a software design pattern in which any dependency object has should be provided that dependency instead of internally create with in an object. The term DI was coined by Martin Fowler. ● It is an implementation Dependency inversion principle. The principle states: a)High-level modules should not depend on low-level modules. Both should depend on abstractions. b) Abstractions should not depend on details. Details should depend on abstractions.
  4. 4. class UserDAL{ def getUser(id:String):User={ //returning user from database } } class UserService{ val userDAL=new UserDAL() def getUserInfo(id:String):UserInfo={ val user=userDAL.getUser(id) // do some operation on user data and return UserInfo } } What is wrong ?
  5. 5. class UserDAL{ def getUser(id:String):User={ //returning user from database } } class UserService(userDAL: UserDAL){ def getUserInfo(id:String):UserInfo={ val user=userDAL.getUser(id) // do some operation on user data and return UserInfo } } Is this correct?
  6. 6. class UserDAL{ def getUser(id:String):User={ //returning user from database } } class UserService(userDAL: UserDAL){ def getUserInfo(id:String):UserInfo={ val user=userDAL.getUser(id) // do some operation on user data and return UserInfo } } Is this correct -No
  7. 7. trait UserDALComponent{ def getUser(id:String):User } class UserDAL extends UserDALComponent{ def getUser(id:String):User={ //returning user from database } } class UserService(userDAL: UserDALComponent){ def getUserInfo(id:String):UserInfo={ val user=userDAL.getUser(id) // do some operation on user data and return UserInfo } }
  8. 8. Why should we use it ● Unit testing Mock Data Access Layer Mock File System Mock Email ● Modular design Multiple different implementation Upgradeable infrastructure ● Clean Separations Single Responsibility Increase code Re-Use Cleaner Modeling ● Concurrent or independent development
  9. 9. Implementations ● Constructor injection ● Setter injection ● Cake pattern ● Google-guice ● etc .
  10. 10. Constructor Injection // Data Access Layer trait UserDALComponent { def getUser(id: String): User def create(user: User) def delete(user: User) } class UserDAL extends UserDALComponent { // a dummy data access layer that is not persisting anything def getUser(id: String): User = { val user = User("12334", "testUser", "test@knoldus.com") println("UserDAL: Getting user " + user) user } def create(user: User) = { println("UserDAL: creating user: " + user) } def delete(user: User) = { println("UserDAL: deleting user: " + user) } } case class User(id: String, name: String, email: String) // User service which have Data Access Layer dependency class UserService(userDAL: UserDALComponent) { def getUserInfo(id: String): User = { val user = userDAL.getUser(id) println("UserService: Getting user " + user) user } def createUser(user: User) = { userDAL.create(user) println("UserService: creating user: " + user) } def deleteUser(user: User) = { userDAL.delete(user) println("UserService: deleting user: " + user) }
  11. 11. Setter Injection // Data Access Layer trait UserDALComponent { def getUser(id: String): User def create(user: User) def delete(user: User) } class UserDAL extends UserDALComponent { // a dummy data access layer that is not persisting anything def getUser(id: String): User = { val user = User("12334", "testUser", "test@knoldus.com") println("UserDAL: Getting user " + user) user } def create(user: User) = { println("UserDAL: creating user: " + user) } def delete(user: User) = { println("UserDAL: deleting user: " + user) } } case class User(id: String, name: String, email: String) // User service which have Data Access Layer dependency class UserService() { private var userDAL: UserDALComponent = _ def setUserDAL(userDAL: UserDALComponent) = { this.userDAL = userDAL } def getUserInfo(id: String): User = { val user = userDAL.getUser(id) println("UserService: Getting user " + user) user } def createUser(user: User) = { userDAL.create(user) println("UserService: creating user: " + user) } def deleteUser(user: User) = { userDAL.delete(user) println("UserService: deleting user: " + user) } }
  12. 12. Cake Pattern // Data Access Layer trait UserDALComponent { val userDAL: UserDAL class UserDAL { // a dummy data access layer that is not persisting anything def getUser(id: String): User = { val user = User("12334", "testUser", "test@knoldus.com") println("UserDAL: Getting user " + user) user } def create(user: User) = { println("UserDAL: creating user: " + user) } def delete(user: User) = { println("UserDAL: deleting user: " + user) } } } case class User(id: String, name: String, email: String) // User service which have Data Access Layer dependency trait UserServiceComponent { this: UserDALComponent => val userService: UserService class UserService { def getUserInfo(id: String): User = { val user = userDAL.getUser(id) println("UserService: Getting user " + user) user } def createUser(user: User) = { userDAL.create(user) println("UserService: creating user: " + user) } def deleteUser(user: User) = { userDAL.delete(user) println("UserService: deleting user: " + user) } } }
  13. 13. Cake Implemetation object User extends UserServiceComponent with UserDALComponent { val userService = new UserService val userDAL = new UserDAL } object UserApp extends App { import User.userService._ println(getUserInfo("")) }
  14. 14. Google Guice // Data Access Layer trait UserDALComponent { def getUser(id: String): User def create(user: User) def delete(user: User) } class UserDAL extends UserDALComponent { // a dummy data access layer that is not persisting anything def getUser(id: String): User = { val user = User("12334", "testUser", "test@knoldus.com") println("UserDAL: Getting user " + user) user } def create(user: User) = { println("UserDAL: creating user: " + user) } def delete(user: User) = { println("UserDAL: deleting user: " + user) } } case class User(id: String, name: String, email: String) // User service which have Data Access Layer dependency class UserService @Inject()(userDAL: UserDALComponent) { def getUserInfo(id: String): User = { val user = userDAL.getUser(id) println("UserService: Getting user " + user) user } def createUser(user: User) = { userDAL.create(user) println("UserService: creating user: " + user) } def deleteUser(user: User) = { userDAL.delete(user) println("UserService: deleting user: " + user) } }
  15. 15. Guice configuration class DependencyModule extends Module { def configure(binder: Binder) = { binder.bind(classOf[UserDALComponent]).to(classOf[UserDAL]) } }
  16. 16. Object creation By Guice val injector = Guice.createInjector(new DependencyModule) val userService = injector.getInstance(classOf[UserService]) // call userService Methods userService.createUser(User("212","demo","app"))
  17. 17. References ● A very popular blog on DI by Jonas boner: http://jonasboner.com/2008/10/06/real-world-scala- ● Inversion of Control Containers and the Dependency Injection pattern By Martin Fowler: http://martinfowler.com/articles/injection.html
  18. 18. ThanksThanks

×