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

avec Java Discussion :

Besoin d'aide pour la compréhension d'une application


Sujet :

avec Java

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2014
    Messages : 24
    Points : 17
    Points
    17
    Par défaut Besoin d'aide pour la compréhension d'une application
    Bonjour,

    Je suis débutant et j'ai un exercice à réaliser mais je ne comprends pas comment m'y prendre pour le réaliser et j'aurais besoin d'aide pour m'aiguiller.

    Voici les différents codes sur lesquels je dois travailler :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    package com.openclassrooms.magicgithub.api;
     
    import com.openclassrooms.magicgithub.model.User;
    import java.util.List;
    import static com.openclassrooms.magicgithub.api.FakeApiServiceGenerator.generateUsers;
     
    public class FakeApiService implements ApiService {
     
        private final List<User> users = generateUsers();
     
        /**
         * Return a list of {@link User}
         * Those users must be generated by {@link FakeApiServiceGenerator}
         */
        @Override
        public List<User> getUsers() {
            // TODO: A modifier
            return null;
        }
     
        /**
         * Generate a random {@link User} and add it {@link FakeApiService#users} list.
         * This user must be get from the {@link FakeApiServiceGenerator#FAKE_USERS_RANDOM} list.
         */
        @Override
        public void generateRandomUser() {
            // TODO: A modifier
     
        }
     
        /**
         * Delete a {@link User} from the {@link FakeApiService#users} list.
         */
        @Override
        public void deleteUser(User user) {
            // TODO: A modifier
     
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    package com.openclassrooms.magicgithub.repository;
     
    import com.openclassrooms.magicgithub.api.ApiService;
    import com.openclassrooms.magicgithub.model.User;
     
    import java.util.List;
     
    public class UserRepository {
     
        private final ApiService apiService; // TODO: A utiliser
        private Object User;
     
        public UserRepository(ApiService apiService) {
            this.apiService = apiService;
        }
     
        public List<User> getUsers() {
            // TODO: A modifier
            return null;
     
        }
     
        public void generateRandomUser() {
            // TODO: A modifier
     
        }
     
        public void deleteUser(User user) {
            // TODO: A modifier
     
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    package com.openclassrooms.magicgithub.model;
     
    import java.util.Objects;
    import java.util.Random;
    import androidx.annotation.Nullable;
    import static com.openclassrooms.magicgithub.api.FakeApiServiceGenerator.FAKE_USERS_RANDOM;
     
    public class User {
     
        private final String id;
        private final String login;
        private final String avatarUrl;
     
        public User(String id, String login, String avatarUrl) {
            this.id = id;
            this.login = login;
            this.avatarUrl = avatarUrl;
        }
     
        // --- GETTERS ---
        public String getId() { return id; }
        public String getLogin() { return login; }
        public String getAvatarUrl() { return avatarUrl; }
     
        /**
         * Generate random user
         */
        public static User random(){
            return FAKE_USERS_RANDOM.get(new Random().nextInt(FAKE_USERS_RANDOM.size()));
        }
     
        @Override
        public boolean equals(@Nullable Object obj) {
            if (obj == null) return false;
            if (obj == this) return true;
            if (!(obj instanceof User)) return false;
            return (((User) obj).avatarUrl == this.avatarUrl && ((User) obj).login == this.login);
        }
     
        @Override
        public int hashCode() {
            return Objects.hash(login, avatarUrl);
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    package com.openclassrooms.magicgithub.api;
     
    import com.openclassrooms.magicgithub.model.User;
     
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.UUID;
     
    public abstract class FakeApiServiceGenerator {
     
     
        static List<User> generateUsers() {
            return new ArrayList<>(FAKE_USERS);
        }
     
        public static List<User> FAKE_USERS = Arrays.asList(
                new User("001", "Jake", "https://api.adorable.io/AVATARS/512/1.png"),
                new User("002", "Paul", "https://api.adorable.io/AVATARS/512/2.png"),
                new User("003", "Phil", "https://api.adorable.io/AVATARS/512/3.png"),
                new User("004", "Guillaume", "https://api.adorable.io/AVATARS/512/4.png"),
                new User("005", "Francis", "https://api.adorable.io/AVATARS/512/5.png"),
                new User("006", "George", "https://api.adorable.io/AVATARS/512/6.png"),
                new User("007", "Louis", "https://api.adorable.io/AVATARS/512/7.png"),
                new User("008", "Mateo", "https://api.adorable.io/AVATARS/512/8.png"),
                new User("009", "April", "https://api.adorable.io/AVATARS/512/9.png"),
                new User("010", "Louise", "https://api.adorable.io/AVATARS/512/10.png"),
                new User("011", "Elodie", "https://api.adorable.io/AVATARS/512/11.png"),
                new User("012", "Helene", "https://api.adorable.io/AVATARS/512/12.png"),
                new User("013", "Fanny", "https://api.adorable.io/AVATARS/512/13.png"),
                new User("014", "Laura", "https://api.adorable.io/AVATARS/512/14.png"),
                new User("015", "Gertrude", "https://api.adorable.io/AVATARS/512/15.png"),
                new User("016", "Chloé", "https://api.adorable.io/AVATARS/512/16.png"),
                new User("017", "April", "https://api.adorable.io/AVATARS/512/17.png"),
                new User("018", "Marie", "https://api.adorable.io/AVATARS/512/18.png"),
                new User("019", "Henri", "https://api.adorable.io/AVATARS/512/19.png"),
                new User("020", "Rémi", "https://api.adorable.io/AVATARS/512/20.png")
        );
     
        public static List<User> FAKE_USERS_RANDOM = Arrays.asList(
                new User("021", "Lea", "https://api.adorable.io/AVATARS/512/21.png"),
                new User("022", "Geoffrey", "https://api.adorable.io/AVATARS/512/22.png"),
                new User("023", "Simon", "https://api.adorable.io/AVATARS/512/23.png"),
                new User("024", "André", "https://api.adorable.io/AVATARS/512/24.png"),
                new User("025", "Leopold", "https://api.adorable.io/AVATARS/512/25.png")
        );
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.openclassrooms.magicgithub.api;
     
    import com.openclassrooms.magicgithub.model.User;
    import java.util.List;
    import androidx.annotation.Nullable;
     
    public interface ApiService {
        List<User> getUsers();
        void generateRandomUser();
        void deleteUser(User username);
    }
    Dans le premier code j'ai 3 fonctions a modifier
    La première fonction doit retourner la liste d'utilisateur donc je suppose qu'il faut utiliser la variable users en faisant return users
    La deuxième fonction dois générer un utilisateur aléatoirement, j'utilise à nouveau la variable users en faisant users.add(User.random()), j'utilise la fonction random() de la classe User pour générer un utilisateur aléatoire et j'utilise la fonction add() pour ajouter l'utilisateur à la liste dans users
    Pour la troisième fonction je suppose que ç'est users.remove(user) mais je ne comprends pas le lien entre deleteUser(User user) de la classe FakeApiService avec la classe User et l'interface ApiService où la fonction est deleteUser(User username)

    Dans le deuxième code je comprends que je dois utiliser la variable apiService mais je ne comprends pas quoi faire.

    Et je ne comprends pas que fais ce bout de code, même si je sais que c'est un constructeur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     public UserRepository(ApiService apiService) {
            this.apiService = apiService;
        }
    Merci d'avance pour votre aide

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,


    1. Citation Envoyé par tifabulous Voir le message
      Dans le deuxième code je comprends que je dois utiliser la variable apiService mais je ne comprends pas quoi faire.

      Et je ne comprends pas que fais ce bout de code, même si je sais que c'est un constructeur.

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
       public UserRepository(ApiService apiService) {
              this.apiService = apiService;
          }
      Techniquement, ce constructeur permet de créer une instance de UserRepository tel que sa variable apiService soit affectée par une instance de apiService, celle passée en argument du constructeur.
      Fonctionnellement, il s'agit d'avoir un référentiel utilisateur (UserRepository) qui utilise un service (ApiService) pour gérer ses utilisateurs. On cherche à décorréler la gestion d'utilisateurs dans le repository de l'accès à la base d'utilisateurs, c'est-à-dire d'une implémentation du repository indépendante de la façon de gérer l'échange avec le stockage (qui peut être ici dans le "Fake" (ce qu'on appelle un mock, une sorte de simulation), sous forme de liste en mémoire, mais qui pourrait être un fichier, une base de données qu'on accède en JDBC, un service distant (REST ou pas) accédé en HTTP (via Unirest par exemple), etc).

      Du coup, ici l'exercice dans la deuxième classe, est globalement de déléguer les opérations de UserRepository à l'instance de ApiService.


    2. Citation Envoyé par tifabulous Voir le message
      La première fonction doit retourner la liste d'utilisateur donc je suppose qu'il faut utiliser la variable users en faisant return users

      • Pour la classe FakeApiService, effectivement.

      • Dans la classe UserRepository, il n'y a pas de variable users, donc return users, ça va pas le faire.

        Dans l'idée de déléguer à l'ApiService, dans le cas le plus simple, il suffit seulement d'appeler la méthode qui va bien dans le service :

        Code : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        4
        5
        6
         
        public List<User> getUsers() {
         
           return apiService.getUsers();
         
        }
        Bien sûr, on peut complexifier (on peut imaginer que l'accès systématique à une liste d'utilisateurs sur une base distante va poser des problèmes de performances par exemple) : n'ayant pas d'énoncé, je vais me limiter ici à cette simple délégation.

      Citation Envoyé par tifabulous Voir le message
      La deuxième fonction dois générer un utilisateur aléatoirement, j'utilise à nouveau la variable users en faisant users.add(User.random()), j'utilise la fonction random() de la classe User pour générer un utilisateur aléatoire et j'utilise la fonction add() pour ajouter l'utilisateur à la liste dans users
      Oui, c'est bien l'idée dans la classe FakeApiService. Et dans UserRepository, c'est également de la délégation.

      Citation Envoyé par tifabulous Voir le message
      Pour la troisième fonction je suppose que ç'est users.remove(user) mais je ne comprends pas le lien entre deleteUser(User user) de la classe FakeApiService avec la classe User et l'interface ApiService où la fonction est deleteUser(User username)
      Ici, la complexité est un peu plus élevée : l'interface List dispose de deux méthodes remove(), une prenant un int en argument (l'index, soit la position, de l'élément qu'on veut supprimer), et l'autre prenant une référence d'objet, celle qu'on veut supprimer de la liste (ça supprimera la première, vu qu'on pourrait avoir plusieurs fois la même instance dans la List). Il existe une autre méthode, qui s'appelle removeIf() et qui prend un prédicat en argument : j'en parlerai après, ne sachant pas quel niveau de connaissance de Java on te demande pour faire cet exercice.

      Citation Envoyé par tifabulous Voir le message
      [...]ApiService où la fonction est deleteUser(User username)
      Effectivement la méthode est void deleteUser(User username);. Mais je pense soit à une boulette (le sujet a été modifié pour être simplifié et on a oublié de modifier le nom de l'argument), soit un petit coup un peu vicelard dans le but de mettre de la confusion dans ton esprit. Parce que le type de username est bien User, pas un String comme ça devrait être logiquement le cas pour un "nom d'utilisateur". La classe User ne dispose même pas de méthode ou d'attribut relatifs à un gestion de nom.
      Ce n'est pas le nom des variables ou arguments qui compte, mais leur type, mais d'un autre côté, ça montre que le nom des variables est important pour la compréhension d'un code (ce qui justifie de les choisir judicieusement).

      Donc, c'est bien users.remove(user) qu'il faut écrire (avec user l'argument, dont c'est bien le nom dans l'implémentation concrète de deleteUser dans FakeApiService).

      Si on avait, dans APIService, une méthode deleteUser(String userlogin), il faudrait pour l'implémenter, rechercher l'instance de User dans la liste users, pour déterminer son index (ou déterminer l'instance de User), puis appeler la méthode remove() avec cet index en argument, ou l'instance trouvée. La méthode removeIf() dont je parlais permet d'effectuer cette tâche en passant le test de sélection en argument de la méthode, par expression lambda, ce que tu verras probablement bien plus tard dans ton processus d'apprentissage.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2014
    Messages : 24
    Points : 17
    Points
    17
    Par défaut
    Bonjour,

    Merci pour ta réponse et tes explications.

    Comme dit dans mon premier message je suis débutant, je commence tout juste la programmation et je n'ai pas encore le vocabulaire qui va bien.

    Je ne comprends pas ce que ça veut dire

    On cherche à décorréler la gestion d'utilisateurs dans le repository de l'accès à la base d'utilisateurs, c'est-à-dire d'une implémentation du repository indépendante de la façon de gérer l'échange avec le stockage
    En fait je ne comprends pas à quoi sert la classe UserRepository même si tu m'explique que c'est pour avoir un référentiel utilisateur (UserRepository) qui utilise un service (ApiService) pour gérer ses utilisateurs.
    Le fonctionnement reste très flou.
    Ce qui fait que je ne comprends pas pourquoi écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public List<User> getUsers() {
     
       return apiService.getUsers(); 
    }
    Pourquoi rappeler la fonction dans la même fonction ?
    Est ce qu'il y a un rapport avec la récursivité ?

    Pour les deux autres fonctions je suppose que c'est ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public void generateRandomUser() {
     
            apiService.generateRandomUser();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        public void deleteUser(User user) {
            // TODO: A modifier
            apiService.deleteUser(user);
    }
    Deuxième point que je ne comprends pas, c'est le paramètre user que ce soit dans la classe UserRepository et l'interface ApiService qu'il y a dans la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public void deleteUser(User user)
    Je ne comprends pas le lien entre ce paramètre et la classe User
    Car je vois aucune variable ou paramètre d'une fonction portant ce nom là dans la classe User.

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tifabulous Voir le message
    En fait je ne comprends pas à quoi sert la classe UserRepository même si tu m'explique que c'est pour avoir un référentiel utilisateur (UserRepository) qui utilise un service (ApiService) pour gérer ses utilisateurs.
    Le fonctionnement reste très flou.
    C'est un fondement de la programmation objet : séparer les traitements (isolation). Ici, on cherche à définir deux objets, un dont le but est de gérer un référentiel utilisateur (UserRepository) et l'autre de gérer un service qui fournit des données (des utilisateurs). Les buts sont multiples. Le principal est de simplifier les traitements : chaque objet est chargé de faire ce qu'il doit faire et pas faire ce qu'un autre objet est censé faire. Un autre objectif est de pouvoir réutiliser, combiner, les objets à différentes fins, sans avoir à réécrire plusieurs le même code. Dans le cas de UserRepository et de ApiService qui fournit des Users, on pourrait imaginer par exemple une classe dont le but est d'envoyer des emails à des utilisateurs (pour faire du publipostage), ce qui n'est pas une fonctionnalité liée à la gestion d'utilisateurs (lister, créer, supprimer, etc), mais qui a besoin d'une liste d'utilisateurs pour utiliser leur email pour leur envoyer un email.
    Ou encore, pour faire référence à une donnée existante dans la classe User, on pourrait imaginer un composant qui fait appel à un service d'IA pour faire de la reconnaissance de visages des utilisateurs, qui utiliserait donc l'attribut avatarUrl de User : ce service n'ajoute ni supprime des utilisateurs, il a une méthode List<User> getFaces(String photoUrl) qui va fournir la liste des Users reconnus dans une photo passée en argument.
    Un autre but est de pouvoir adapter rapidement une fonctionnalité technique selon les besoins, sans avoir à réécrire le code de tous les composants (réécrire le code est non seulement chronophage mais également source possible d'erreurs. En permettant de changer facilement par exemple entre un stockage en base locale, en service distant http (non jdbc), on peut facilement juste changer l'APIService, sans avoir à modifier le code de UserRepository (l'intérêt du changement peut être ici la sécurisation dans le cadre d'un site web par exemple, JDBC étant peu fiable dans ce cadre : lorsqu'on met au point le programme, on fonctionne en local en JDBC et quand on déploie sur un site d'hébergement, on échange par services).

    Bien sûr dans un petit programme comme celui de cet exercice, ça semble un peu fastidieux de devoir faire ça, mais dans un programme réel, les fonctionnalités peuvent être nombreuses. En isolant les fonctionnalités par petits groupes, on réduit la taille des classes, on réduit la complexité de ces classes, on limite les possibilités d'erreurs. On limite également l'impact mémoire (si on charge uniquement les classes qu'on a besoin pour les fonctionnalités restreintes qu'on va utiliser. Une application pourrait fournir un APIService pour 50 moyens différents de charger des users, alors qu'on en a besoin que d'un seul à priori pour une application, éventuellement quelques autres si on voulait faire de l'import-export. Tiens, voilà un autre exemple : si on veut pouvoir faire de l'import des users, ou de l'export, entre notre base de données accessible par service, on pourra enchaîner des APIService permettant de lire ou sauver vers de l'Excel, du CSV, etc, des fonctionnalités qui n'ont pas de rapport avec la gestion d'utilisateurs précisément.
    Le but de l'exercice est en partie de te faire aborder ces concepts.

    Citation Envoyé par tifabulous Voir le message
    Ce qui fait que je ne comprends pas pourquoi écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public List<User> getUsers() {
     
       return apiService.getUsers(); 
    }
    Pourquoi rappeler la fonction dans la même fonction ?
    Est ce qu'il y a un rapport avec la récursivité ?
    Alors ce n'est la même méthode : elle porte juste le même nom (parce qu'elle fait la même chose, en terme fonctionnel, récupérer une liste d'utilisateurs). Mais ce sont deux méthodes différentes, puisque deux méthodes de deux objets différents, qui plus est, de classe et interface différentes (UserRepository et APIService), et qui n'ont pas de liens d'héritage.
    On parle de délégation ici, parce que la classe UserRepository délègue la fonctionnalité de récupération de liste de Users à une autre classe FakeApiService, avec laquelle elle communique via l'interface (parce que UserRepository veut avoir une liste de Users, mais se moque de comment et d'où elle est obtenue).

    Et non, il ne s'agit pas de récursivité. La récursivité impliquerait l'appel d'une méthode par elle-même (la même méthode du même objet), mais également, et surtout, une condition d'arrêt (sinon récursion infinie).

    Citation Envoyé par tifabulous Voir le message
    Pour les deux autres fonctions je suppose que c'est ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public void generateRandomUser() {
     
            apiService.generateRandomUser();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        public void deleteUser(User user) {
            // TODO: A modifier
            apiService.deleteUser(user);
    }
    Exactement.


    Citation Envoyé par tifabulous Voir le message
    Deuxième point que je ne comprends pas, c'est le paramètre user que ce soit dans la classe UserRepository et l'interface ApiService qu'il y a dans la fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public void deleteUser(User user)
    Je ne comprends pas le lien entre ce paramètre et la classe User
    Car je vois aucune variable ou paramètre d'une fonction portant ce nom là dans la classe User.
    Le paramètre user est du type User. La méthode est chargée de supprimer un utilisateur de la liste que l'APIService est censée fournir par sa méthode getUsers().
    La classe User n'a pas besoin d'avoir d'attribut ou méthode en lien avec cette fonctionnalité.

    C'est comme ranger des pièces de monnaie dans des boites (prenons le cas d'un numismate qui collectionne des pièces) : les pièces, quelles qu'elles soient, n'ont pas été fabriquées dans le but d'être mises dans des boites, ni fabriquées pour s'adapter à la mise dans des boites. On choisit des boites dont la taille permet de stocker les pièces, dont les caractéristiques permettent de les stocker correctement, pour qu'elles ne s'usent pas, ne se corrodent pas, etc. Les pièces n'ont pas avoir à s'adapter au fait que des numismates veulent les conserver d'une certaine manière.

    Les User n'ont pas à savoir qu'on peut les gérer dans des listes, et qu'on pourrait les ajouter, les supprimer de ces listes. Il n'y a donc pas de méthode de suppression de User dans la classe User. Cela poserait un vrai problème au niveau du code : parce que ça obligerait à User de savoir où et comment un User est stocké et comment il doit être supprimé. Cette fonction technique pouvant être très différente entre un stockage en base, dans un fichier texte, Excel ou via un service API REST par exemple, que ça obligerait User a avoir un lien vers le système qui le stocke. Non seulement ça ajouterait de la complexité inutile (un User peut exister en dehors de tout stockage, il n'a pas besoin d'être stocké), et un User pourrait être stocké dans différents systèmes différents, ce qui l'obligerait à connaître tous ces systèmes, à permettre au code qui a besoin de supprimer d'indiquer de quel système il doit être supprimé, etc. On gère donc le User et le stockage de User, à part, sans interdépendance forte. Bon, dans certains cas, tu verras plus tard, qu'on peut mettre en place des architectures un peu différentes (par exemple, visiteur), mais, ici, le but de l'exercice est de te faire aborder le concept d'isolation de manière simple.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2014
    Messages : 24
    Points : 17
    Points
    17
    Par défaut
    Merci pour tes explications.
    J'ai compris que c'était pour optimiser l'efficacité du code et de l'application, même si différents points sont encore flou.
    Il va me falloir un peu de temps pour digérer tout ça.

    Un dernier point par rapport au lien entre ApiService, FakeApiService et UserRepository

    De ce que j'ai compris l'interface ApiService déclare des fonctions sans en décrire le fonctionnement et ses fonctions peuvent être utilisés par d'autres classes qui décrivent ce que fait le fonctions.

    Dans UserRepository, le code suivant dit que l'on utilise la fonction déclarée dans ApiService pour décrire le fonctionnement de la fonction dans UserRepository ou je suis à l'ouest ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public List<User> getUsers() {
     
            return apiService.getUsers();
     
    }
    Tu dis que UserRepository délègue la fonctionnalité de récupération de liste de Users à une autre classe FakeApiService.
    Seulement je vois aucun lien entre UserRepository et FakeApiService, il n'y a pas d'import de l'un ou de l'autre vers l'un ou l'autre.
    Comment UserRepository délègue la fonctionnalité à FakeApiService ? Comment ces deux classes peuvent communiquer ?

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tifabulous Voir le message
    De ce que j'ai compris l'interface ApiService déclare des fonctions sans en décrire le fonctionnement et ses fonctions peuvent être utilisés par d'autres classes qui décrivent ce que fait le fonctions.
    En gros, c'est ça.

    On dit qu'une interface définit un contrat. Elle définit les méthodes qui doivent être implémentées dans une classe qui choisit d'implémenter celle-ci. Ce qui signifie qu'un code qui manipule un objet d'une classe qui implémente l'interface a à sa disposition au moins les méthodes que déclare l'interface.


    Citation Envoyé par tifabulous Voir le message
    Dans UserRepository, le code suivant dit que l'on utilise la fonction déclarée dans ApiService pour décrire le fonctionnement de la fonction dans UserRepository ou je suis à l'ouest ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public List<User> getUsers() {
     
            return apiService.getUsers();
     
    }
    En gros, c'est ça.
    Ici, on a l'invocation (l'appel) d'une méthode de ApiService. On décrit bien que la méthode getUsers() de UserRepository va faire appel la méthode getUsers() de ApiService pour faire ce qu'elle doit faire. Ici, comme on manipule un objet via son interface, on ignore volontairement comment c'est décrit à l'intérieur de la méthode de l'implémentation concrète (de la méthode dans la classe concrète, dans l'exemple FakeApiService) : on ne s'intéresse qu'à la méthode de l'interface, et on ne cherche pas à savoir comment elle est implémentée au final.



    Citation Envoyé par tifabulous Voir le message
    Tu dis que UserRepository délègue la fonctionnalité de récupération de liste de Users à une autre classe FakeApiService.
    Seulement je vois aucun lien entre UserRepository et FakeApiService, il n'y a pas d'import de l'un ou de l'autre vers l'un ou l'autre.
    Comment UserRepository délègue la fonctionnalité à FakeApiService ? Comment ces deux classes peuvent communiquer ?
    Le lien va se faire à l'instanciation, lorsqu'on va passer une instance de FakeApiService en argument du constructeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Program {
        public static void main(String[] args) {
     
               ApiService apiService = new FakeApiService(); // on créé une instance de FakeApiService
               UserRepository userRepository = new UserRepository(apiService); // on créé une instance de UserRepository qui va utiliser l'instance de classe FakeApiService, via l'interface ApiService
               System.out.println("Liste des utilisateurs : " + userRepository.getUsers()); // on affiche la liste des utilisateurs via la méthode getUsers() de UserRepository, qui va appeler la méthode getUsers() de ApiService, qui sera concrètement implémentée dans FakeApiService
     
     
        }
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2014
    Messages : 24
    Points : 17
    Points
    17
    Par défaut
    Donc si j'ai bien compris, vu que UserRepository importe ApiService et que FakeApiService implémente ApiService, UserRepository a accès aux méthodes et données de FakeApiService ?

    Je sais pas si je suis très clair.

  8. #8
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tifabulous Voir le message
    Donc si j'ai bien compris, vu que UserRepository importe ApiService et que FakeApiService implémente ApiService, UserRepository a accès aux méthodes et données de FakeApiService ?
    Oui.

    Pour être plus précis :

    • La classe UserRepository a une variable de type ApiService, ce qui lui permet d'invoquer les méthodes de ApiService sur l'instance référencée par cette variable. L'import au sens Java n'est juste là pour permettre au compilateur de savoir de quelle classe/interface il s'agit exactement (parce qu'on pourrait avoir plusieurs classes/interfaces de nom ApiService dans des packages différents.
    • Cependant, UserRepository n'a pas accès aux variables de FakeApiService, pas directement en tout cas et c'est un autre principe de la programmation objet : l'encapsulation. Mais effectivement, par appel de la méthode getUsers() de FakeApiService (et de par son implémentation), la classe FakeApiService laisse accès aux données qu'elles gèrent, d'une façon qu'elle (FakeApiService) décide (en l'occurence, elle laisse accès à toutes ses données). Donc effectivement l'instance de UserRepository a accès aux données de l'instance de FakeApiService, enfin aux instances de User, parce UserRepository ne peut pas changer la référence de l'objet stocké dans la variable users de FakeApiService.

      On est dans le cadre d'un exercice de débutant et on limite en quelque sorte l'implémentation a des concepts limités, le but étant d'aborder certains concepts. Par exemple, on pourrait, si on voulait aller plus loin, empêche UserRepository de manipuler la liste que FakeApiService gère. Parce qu'en l'occurrence, l'implémentation de la méthode getUsers() telle que tu l'as faite fait que la liste de User gérée au sein de FakeApiService transite entre les deux classes, ce qui fait que UserRepository pourrait faire un peu près tout ce qu'elle veut sur cette liste (et même faire dysfonctionner FakeApiService). Maintenant, n'ayant pas l'énoncé exact, je ne connais pas la limite de ce qu'on cherche à obtenir comme code au final.

      On pourrait par exemple pousser un peu plus loin :
      Si dans FakeApiService, on implémente getUsers() comme ça :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      public List<User> getUsers() {
           List<User> copy = new ArrayList<>(users); // crée une nouvelle liste avec le contenu de users (de FakeApiService), soit toutes les instances de User qu'elle contient
           return copy;  // retourne une copie de la liste
      }
      UserRepository peut faire tout ce qu'elle veut sur la liste récupérée par l'appel de apiService.getUsers(), ça ne modifiera pas la liste gérée par FakeApiService, mais juste sa copie. Elle sera donc obligée d'appeler apiService.deleteUser() pour supprimer un user de la liste gérée au sein de FakeApiService. Sauf que de la même manière, si FakeApiService modifie la liste qu'elle possède, la copie ne sera pas modifiée, ce qui peut être un avantage ou un inconvénient dans UserRepository selon la manière dont va écrire son code, sans parler des inconvénients de la copie en elle-même (plus de mémoire, temps faire la copie).

      Pour aller un peu plus loin encore, on pourrait écrire la méthode getUsers() dans FakeApiService comme ça :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      public List<User> getUsers() {
           return java.util.Collections.unmodifiableList(users); // crée une nouvelle liste avec le contenu de users (de FakeApiService), qui n'est pas modifiable et retourne cette liste 
      }
      Ici, la liste gérée par FakeApiService est intégrée dans une classe qui empêche toute modification "de l'extérieur" : c'est par cette classe que UserRepository aura accès à la liste, donc ne pourra pas la modifier directement et sera donc bien obligée de passer par les méthodes de l'interface ApiService pour le faire (supprimer un utilisateur, comme en ajouter un aléatoirement). En revanche, FakeApiService, par sa variable users pourra continuer à ajouter ou supprimer de utilisateurs dans la liste.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  9. #9
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Tiens, en poussant un peu la lecture de l'énoncé, je viens de voir dans la méthode de la classe User, que je n'avais pas vu avant, un code très douteux (d'autant plus douteux que le résultat de son exécution est un des pièges les plus courants dans lequel les débutants en Java tombe) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return (((User) obj).avatarUrl == this.avatarUrl && ((User) obj).login == this.login);


    On ne compare jamais des String (entre autres) par == mais par la méthode equals. Le signe == va comparer les références et rien ne permet d'affirmer que deux instances de users de même login par exemple, donc dont on peut supposer qu'elles soient égales fonctionnellement, rien ne permet d'affirmer donc que ces deux instances soient considérées comme égales par la méthode equals(), car deux instances de String de même valeur sont logiquement égales, mais pas identiques.
    Bon, dans le cadre de l'implémentation des méthodes qu'on demande dans l'exercice, ça n'a pas d'importance en soi, à part que ça donne un mauvais exemple, sans parler d'un code qui ne fonctionnera pas forcément.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2014
    Messages : 24
    Points : 17
    Points
    17
    Par défaut
    Merci à toi pour ton aide et ta patience, je comprends mieux ce qui se passe.

    Le but de l'exercice était de modifier le code dans FakeApiService et UserRepository notamment les 3 fonctions pour que l'application puisse fonctionner, tout le reste du code était déjà écrit.
    Il fallait en plus effectuer des tests unitaire et instrumentalisé en échec et en succès.

    Le code de base était :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    public List<User> getUsers() {
            // TODO: A modifier
           return null;
    }
     
     
    public void generateRandomUser() {
            // TODO: A modifier
    }
     
     
    public void deleteUser(User user) {
            // TODO: A modifier
    }
    Merci pour l'info pour la fonction equals()

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Besoin d'aide pour la réalisation d'une application
    Par stevenakoumia dans le forum ASP.NET
    Réponses: 1
    Dernier message: 25/09/2018, 11h06
  2. besoin d'aide pour la création d'une requête
    Par fabien59420 dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 11/06/2008, 15h29
  3. Réponses: 3
    Dernier message: 26/06/2007, 14h53
  4. Réponses: 2
    Dernier message: 10/03/2006, 13h55

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