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

Design Patterns Discussion :

Éclater une classe VoitureManager


Sujet :

Design Patterns

  1. #1
    Membre éclairé
    Éclater une classe VoitureManager
    Bonjour, j'ai une classe VoitureManager et elle commence à être un peu lourde, je voudrais bien la spliter en plusieurs design patter mais il reste quelques fonctions que je ne sais pas où mettre. Pour l'instant VoitureManager devient :

    • VoitureFactory pour créer mes voitures et les stocker dans une list :
      void Add(Voiture v) { listDeVoiture.Add(v); }.
    • VoitureMediator pour faire communiquer mes voitures avec mon interface :
      Voiture get(int idVoiture) { return listDeVoiture[id]; }.
    • Voiture****** pour faire rouler mes voitures avec mon interface :
      int rouler(idVoiture) { listDeVoiture[id].roule(); return listDeVoiture[id].vitesse; }.


    Il me manque mon 3e design pattern qui me permet d'utiliser mes voitures en cliquant sur un bouton depuis mon interface.

    Vous avez des idées ou des choses à me conseiller ?



    PS : Il ne s'agit pas vraiment de voiture.

  2. #2
    Membre émérite
    Alors ne le prends pas mal mais pour moi, le code ressemble fortement à un excès d'enthousiasme vis-à-vis des design patterns

    Je préfère largement un programme où les responsabilités sont bien découpées entre l'UI, la logique métier et la base de données (pour faire simple) sans aucun design pattern, à une structure de classes où on a cherché à faire rentrer du pattern au forceps sans en avoir réellement besoin. A la rigueur, les patterns tu devrais en faire même sans le savoir.

    Les design patterns ont tous dans leur définition une partie Intention et Motivation qui explique à quel type de problématique répond le patron et ce qu'il apporte. Cela peut être une solution astucieuse à un problème difficile, plus de maintenabilité, de la performance... mais l'idée est d'ouvrir ta boite à outils de patterns avec un problème précis que tu n'arrives pas à résoudre, pas de chercher je ne sais quelle sophistication ou standardisation quand tu sais déjà qu'il y a une implémentation très simple possible.

    Pour splitter une classe trop grosse je me tournerais plutôt vers du refactoring traditionnel de type Extract Class avec en tête le Single Responsibility Principle.

  3. #3
    Membre éclairé
    Entièrement d'accord avec toi mais juste que là dans mon projet je commence à avoir plusieurs fichier dépassant les 800 lignes de code et ce n'est pas bon. Malheureusement je ne sais pas encore trop bien comment découper ça.

  4. #4
    Membre éclairé
    Personne ?
    Aucune autre réponse ? À croire que plus personne ne fait de l'UML de nos jours

  5. #5
    Membre émérite
    Ben, c'est difficile de conseiller un découpage quand on n'a pas sous les yeux le code en question

    Les deux gros axes d'organisation du code peuvent être :

    • Les couches applicatives : UI, business, data access, etc. Ne pas mélanger des responsabilités de plusieurs couches dans la même classe.
    • Responsabilité bien définie à attribuer à chaque classe : représenter un type d'entité (voiture ou autres), lecture, écriture, logique métier...


    Là on dirait que tu as tout mis dans un gros Manager qui fait le ménage et le café à propos des Voitures et la question laisse penser que tu as mélangé des responsabilités de plusieurs couches dedans...

    PS : les design patterns et les bonnes pratiques de conception orientée objet en général n'ont pas de lien direct avec UML

  6. #6
    Membre éclairé
    C'est un peu le problème dans mon code. Pour faire simple j'ai 4 classes, ma classe Database, ma classe GUI, ma classe Voiture et ma classe VoitureManager et du coup ma classe VoitureMaganer permet de faire le lien entre Voiture, Database et GUI car je sais pas trop comment lier le tout. En gros j'utilise un model MVC mais j'ai un peu du mal à faire le lien entre mes 3 parties.

  7. #7
    Membre émérite
    Pourquoi utiliser le terme Manager alors qu'en MVC il existe justement le Controller qui permet de faire l'aiguillage entre ces parties ? Qu'est-ce qui bloque du coup ?

  8. #8
    Membre éclairé
    Ah... Ouais, du coup ça serait un VoitureController plutôt qu'un VoitureManager... Oui sauf que le truc qui me gêne un peu c'est que dans mon manager j'ai du code algorithimique et normalement il n'est pas censé avoir de l'algorithmie dans un Controller. En gros le code que je ne sais pas où mettre est le suivant :
    Code C++ :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    voiture FaireLaCourse(Circuit circuit, List<Voiture> participants) { // executer au clique d'un bouton
        for(auto paticipant : participants) {
             paticipant.roule(circuit);
        }
        participants = ordonnerParTempsDarrive(participants);
     
        return participants[0]; // retourne le vainqueur pour que la GUI l'affiche
    }


    Ce code n'appartient ni à Voiture, ni à Circuit, ni à la GUI, ni à la DataBase ... (Au Controller non plus ?) ... Je ne sais pas où mettre ce bout de code. C'est pour ça que j'ai fait un VoitureController, mais bon ...

  9. #9
    Membre émérite
    La notion de Course semble être un concept central et elle n'a pas de classe...

  10. #10
    Membre éclairé
    Ouais c'est exactement ça le problème...

  11. #11
    Expert confirmé
    Code cpp :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    voiture FaireLaCourse(Circuit circuit, List<Voiture> participants) { // executer au clique d'un bouton
        for(auto paticipant : participants) {
             paticipant.roule(circuit);
        }
        participants = ordonnerParTempsDarrive(participants);
     
        return participants[0]; // retourne le vainqueur pour que la GUI l'affiche
    }


    Déjà dans ce bout de code je vois au moins 4 problèmes:

    1) tu modifies une liste venant de l'extérieur.
    2) tu retournes un vainqueur alors que la fonction se nomme faireLaCourse, avec ce nom ce n'est pas la responsabilité de cette méthode de retourner le gagnant (et quid si plus tard ton veux retourner les 3 premiers).
    3) tu retournes une voiture en tant que vainqueur, alors que voiture et vainqueur sont deux concepts aux responsabilités différents, si tu veux par exemple étendre ton code avec winner.receivePrize(), ce n'est tout de même pas la classe voiture qui va avoir un attribut prize.
    4) aucune validation des entrées, ton [0] va pas aimer si tu passes une liste vide.

    Enfin comme dit précédemment, un handler, ou un controller, ou un service... sont des concepts techniques (la couche infra en DDD), alors qu'une voiture, un circuit, une course, sont des concepts fonctionnels, faisant partie du domain model.
    Une méthode fonctionnelle comme "faire la course" ne doit pas se retrouver dans un composant technique.

    Un handler est là pour te donner la liste de toutes les voitures, une voiture par id, créer une voiture depuis une factory...

    Les patterns existent pour solutionner des problématiques, pas pour en inventer de nouvelles.
    Play50HZ, le retro-gaming facile: Essayez-le

    Yildiz-Engine an open-source modular game engine: Website
    Yildiz-Online a 3D MMORTS in alpha: Facebook page / Youtube page

###raw>template_hook.ano_emploi###