IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Scala Java Discussion :

Scala et injection de dépendances


Sujet :

Scala Java

  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 36
    Par défaut Scala et injection de dépendances
    En surfant un peu, j'ai trouvé l'article suivant:
    http://jonasboner.com/2008/10/06/rea...ection-di.html
    Celui-ci explique que Scala possède au niveau du langage tout le nécessaire pour faire de l'injection de dépendances - donc sans requérir l'utilisation d'un framework spécialisé.

    Je ne vais pas répéter l'ensemble de l'article ici, mais au final, toute la configuration se fait dans un object Scala "ordinaire":
    Code scala : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        object ComponentRegistry extends   
          UserServiceComponent with   
          UserRepositoryComponent   
        {  
          val userRepository = new UserRepository  
          val userService = new UserService  
        }
    Et quand à l'utilisation elle se fait le plus simplement du monde, sans avoir à se préoccuper du "câblage" des composants:
    Code scala : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      val userService = ComponentRegistry.userService  
      val user = userService.authenticate(..)

    Un argument fort qui est cité est que l'ensemble est statiquement typé. Ce qui permet au compilateur de détecter les incohérences de type - et réduit les surprises au déploiement.


    Que pensez-vous de ce genre de technique? Est-ce que l'argument de la vérification des types donne vraiment un avantage concurrentiel à Scala sur ce point? Est-ce que cela pourrait motiver votre adoption de ce langage?


    - Sylvain

  2. #2
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut
    Réponse un peu en retard mais bon

    Ce que l'on n'oublie c'est qu'un framework comme Spring permet l'externalisation de la configuration via les fichiers XML. On peut parcourir l'application sans rentrer dans le code.

    Je trouve le couplage trop fort avec une solution comme celle-là. Avec Spring, l'instanciation de l'objet est cachée et on a plus de contrôle sur le cycle de vie de l'objet, tout ça avec un couplage beaucoup plus faible

  3. #3
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut Contruction monadique des dépendances
    Voici une technique "d'injection de dépendances" que j'utilise dans mes projets Scala. Je la trouve personnellement plus fonctionnelle.

    Tout abord, définissons le trait Functor:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    trait Functor[F[_]] {
      def map[A, B](m: F[A])(f: A => B): F[B]
    }
    puis la monad Free comme suit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    trait Free[F[+_], A] {
      def map[B](f: A => B)(implicit F: Functor[F]) = flatMap(a => Done(f(a)))
     
      def flatMap[B](f: A => Free[F, B])(implicit F: Functor[F]) = this match {
        case Done(a) => f(a)
        case More(m) => More(F.map(m)(_ flatMap f))
      }
    }
     
    case class Done[F[+_], A](v: A) extends Free[F, A]
    case class More[F[+_], A](f: F[Free[F, A]]) extends Free[F, A]
    Définissons maintenant nos dépendances:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    trait Dependency[+A]
    case class GetUserRepository[A](f: UserRepository => A ) extends Dependency[A]
    case class GetUserService[A](f: UserService => A ) extends Dependency[A]
    Nous pouvons maintenant définir un functor pour le trait Dependency:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    new Functor[Dependency]{
      def map[A, B](d: Dependency[A])(f: A => B) = d match {
        case GetUserRepository(g) => GetUserRepository(x => f(g(x)))
        case GetUserService(g)     => GetUserService(x => f(g(x)))
      }
    }
    Définissons maintenant l'objet Provider qui nous permet de construire "nos dépendances"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    object Provider {
      def getUserRepository: Free[Dependency, UserRepository] =
        More(GetUserRepository(rep => Done(rep)))
     
      def getUserService: Free[Dependency, UserService] =
        More(GetUserService(ser => Done(ser)))
    }
    Nous pouvons maintenant construire nos dépendances à la demande monadiquement comme cela par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    import Provider._
     
    for {
      repo     <- getUserRepository
      service <- getUserService
    } yield ma_fonction(repo, service)
    avec ma_fonction la fonction qui a besoin des dépendances

    Maintenant passons à l'injection à proprement parlé. Définisson le trait Environment comme suit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    trait Environment {
      val repository: UserRepository
      val service: UserService
    }
    Avec par exemple cette config de dev:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    object DEV extends Environment  {
      lazy val repository = new UserRepositoryDeDev
      lazy val service = new UserServiceDeDev
    }
    Voici maintenant le fameux "injecteur"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    @tailrec
    def resolve[A](needed: Free[Dependency, A])(implicit env: Environment): A = needed match {
      case Done(a) => a
      case More(GetUserRepository(f)) => resolve(f(env.repo))
      case More(GetUserService(f)) => resolve(f(env.service))
    }
    En reprenant notre exemple de tout à l'heure, nous avons maintenant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    import Provider._
     
    val action = for {
      repo     <- getUserRepository
      service <- getUserService
    } yield ma_fonction(repo, service)
     
    resolve(action) // l'injection se passe à ce niveau
    C'est assez dense, mais l'injection de dépendance est un bien grand mot qui peut se résumer à ''Passer un objet en paramètre d'une fonction". Si l'idée vous plait, je pourrais également faire un tutoriel (beaucoup) plus explicatif.

    Que pensez-vous de cette technique ?
    Des points à améliorer ?

  4. #4
    Nouveau membre du Club
    Profil pro
    Dév
    Inscrit en
    Février 2006
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Dév

    Informations forums :
    Inscription : Février 2006
    Messages : 8
    Par défaut
    Citation Envoyé par Yo Eight Voir le message

    C'est assez dense, mais l'injection de dépendance est un bien grand mot qui peut se résumer à ''Passer un objet en paramètre d'une fonction". Si l'idée vous plait, je pourrais également faire un tutoriel (beaucoup) plus explicatif.

    Que pensez-vous de cette technique ?
    Des points à améliorer ?
    Un tutoriel sur la programmation fonctionnelle en Scala? Oui, il serait le bienvenu! Il y en a d'excellents en anglais (par exemple celui d'Eric Torrebore "Essence of Iterator Pattern" ou ceux de Debashih Gosh), mais un en français écrit par un contributeur de Scalaz, ce serait top!
    Si en plus les "monads transformers" sont abordés...(au hasard, ValidationT avec un Writer)

    Benoît

  5. #5
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2009
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2009
    Messages : 97
    Par défaut
    A vrai dire les Monad Transformer viennent du monde Haskell.

    Une grande majorité des contributeurs de Scalaz font de l'Haskell. Ils veulent tous avoir les puissantes api provenant de ce langage (compréhensible car elles sont terriblement efficaces)

    Le problème c'est que l'inférence de type en Scala ne fonctionne pas très bien avec ce style et les signatures des méthodes deviennent effrayantes pour les néophytes (tu as du le remarquer quand tu regardes le code source de ValidationT.scala ).

    Un tutoriel sur la programmation fonctionnelle en Scala ? Pourquoi pas mais ça sera que des traductions Anglais => Français ou des ports Haskell => Scala car le sujet a été depuis 2007 beaucoup discuté dans la communauté Scala. Haskell couvre ces sujets depuis au moins une dizaine d'années. Mais pourquoi pas .

    Quand à l'utilisation d'un ValidationT avec un Writer, je veux bien te fournir un exemple qui compile si tu n'arrives pas avec les modifs que j'ai mis sur StackOverflow.

    Il semble qu'il y ait un problème avec le type Id. Depuis la réécriture de scalaz-seven, Id est exprimé comme suit:

    Code Scala : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    type Id[A] = A

    Alors que dans Scalaz 6, c'était fait par une conversion implicite vers ce trait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    sealed trait Id[A]{
      ...
    }
    Il y a peut-être une régression avec certaines typeclass (comme Pointed).

    Si tel était le cas, je proposerais un fix

  6. #6
    Nouveau membre du Club
    Profil pro
    Dév
    Inscrit en
    Février 2006
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Dév

    Informations forums :
    Inscription : Février 2006
    Messages : 8
    Par défaut
    Ce qui pourrait être intéressant, c'est un (ou des) tuto(s) sur les patterns de la programmation fonctionnelle en scala. Un peu du genre de ce que tu as écrit dans cette discussion où tu montres à quoi sert une monad Free.

    Pour en revenir à scalaz, c'est vrai que les signatures des fonctions sont pour le moins redoutables! Mais je pense que cette librairie apporte un vrai confort. Je l'ai expérimenté avec Validation. Quant à notre discussion sur Stackoverflow, je te remercie encore sincèrement de ton aide, mais le code que tu as posté ne compile toujours pas chez moi (j'ai édité le post...)


    Un cookbook sur scalaz serait quand même le bienvenu!

    Benoît

Discussions similaires

  1. Réponses: 2
    Dernier message: 17/05/2010, 23h18
  2. Réponses: 0
    Dernier message: 08/05/2010, 18h57
  3. [EJB3] Injection de dépendance et Stateful
    Par newbeewan dans le forum Java EE
    Réponses: 1
    Dernier message: 15/05/2007, 08h33
  4. [Integration] [EasyMock] Injection de dépendance à l'éxécution
    Par frangin2003 dans le forum Spring
    Réponses: 2
    Dernier message: 06/03/2007, 12h06
  5. Spring + TagSupport et injection de dépendance
    Par worldchampion57 dans le forum Spring Web
    Réponses: 2
    Dernier message: 26/02/2007, 10h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo