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

Python Discussion :

organiser le code 2


Sujet :

Python

  1. #1
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut organiser le code 2
    Salut,

    J'ouvre ce fil pour ne pas embrouiller l'autre fil : organiser le code 1

    J'aimerais savoir comment vous faites pour organiser votre code dans certaines situations :

    Exemple 2 :

    Une interface graphique dans laquelle il y a plein d'onglets (frames)...

    Chacun d'eux contient des champs de saisi, des boutons...

    Pour l'instant j'utilise une class pour chaque onglet...

    Il y a par exemple des méthodes qui sont exécutées chaque fois qu'une donnée est saisie (par exemple pour mettre à jour les autres champs)...

    Le problème c'est que les class (pour chaque onglet) peuvent dépendre les unes des autres mais que je voudrais quand même séparer le code dans différents fichiers...


    Pour l'instant je fais du bricolage pareil que dans l'exemple de l'autre fil...

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Le problème c'est que les class (pour chaque onglet) peuvent dépendre les unes des autres mais que je voudrais quand même séparer le code dans différents fichiers...
    "peuvent dépendre" ne dit rien sur la relation de dépendance... mais effectivement, on ne pourra pas construire cela sans avoir travaillé la relation de dépendance entre classes(*) ou en utilisant des relations clés en main comme le propose Qt avec slots/signaux.
    (*) et on est toujours dans de la POO... et l'existence de forums plus adaptés.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Ah il y a une solution avec Qt... C'est donc que cela ne doit pas être aussi simple qu'on pourrait le croire...

    Bon ben ça me rassure quelque part...

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Techniquement cela réalise un pattern appelé observer comme mentionné dans cet article de wikipédia. Avec Tk, on peut réaliser la même chose en utilisant des Variables (si on veut faire çà côté Tk) où avec des class python.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Il faudra que je regarde ça attentivement mais à première vue cela me fait penser aux Custom Events en JS...

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Beginner. Voir le message
    Le problème c'est que les class (pour chaque onglet) peuvent dépendre les unes des autres mais que je voudrais quand même séparer le code dans différents fichiers...
    Cela ne doit pas être. Chaque onglet a son propre objet et ça c'est bien. Ensuite on peut penser que la saisie/boutons de l'onglet est indépendant de tous les autres donc quand l'utilisateur fait sa saisie, la saisie est validée puis il passe à un autre onglet et idem. Et là ça marche.

    Mais on a aussi le droit de dire que la saisie de l'onglet 2 dépend de ce qui a été saisi dans l'onglet 1 (imaginons une saisie un peu complexe donc découpée) et dans ce cas il faut passer par une espèce d'objet de contrôle.
    Chaque onglet doit avoir un signal type "saisie terminée" qui est envoyé quand tous les champs qui le concernent sont bien remplis ; et l'objet "contrôle" associe ce signal à un slot chez-lui qui centralise la saisie de l'onglet.
    Ensuite quand on passe à l'onglet suivant celui-ci récupère du contrôle les valeurs des autres onglets pour faire sa propre cuisine et etc. Il doit avoir une méthode "onShow()" dans un onglet qui permet de faire une action quand il est appelé. Et l'action c'est donc de récupérer de l'objet de contrôle les éléments dont il a besoin.

    Et au final l'objet de contrôle, quand tout a été saisi, s'occupe alors de l'enregistrement de la saisie en bdd.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Il faudra que je regarde ça attentivement mais à première vue cela me fait penser aux Custom Events en JS...
    Il n'y a rien de très original la dedans... Et ce n'est pas difficile à réaliser avec Python voir par exemple le source d'events sur PyPI.
    Mais cela reste une façon parmi d'autre pour relier des objets....
    Suivant le cas d'autres méthodes seront plus pertinentes.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Il n'y a rien de très original la dedans... Et ce n'est pas difficile à réaliser avec Python voir par exemple le source d'events sur PyPI.
    Ah oui cela correspond bien aux Custom Events en JS... Il y a aussi une class dans node.js et même PHP...

    Citation Envoyé par Sve@r Voir le message
    Mais on a aussi le droit de dire que la saisie de l'onglet 2 dépend de ce qui a été saisi dans l'onglet 1 (imaginons une saisie un peu complexe donc découpée) et dans ce cas il faut passer par une espèce d'objet de contrôle.
    Oui c'est plus ce genre de situation et même plus compliqué : la dépendance pourrait aller dans les deux sens...

    Citation Envoyé par Sve@r Voir le message
    Chaque onglet doit avoir un signal type "saisie terminée" qui est envoyé quand tous les champs qui le concernent sont bien remplis ; et l'objet "contrôle" associe ce signal à un slot chez-lui qui centralise la saisie de l'onglet.
    Ensuite quand on passe à l'onglet suivant celui-ci récupère du contrôle les valeurs des autres onglets pour faire sa propre cuisine et etc. Il doit avoir une méthode "onShow()" dans un onglet qui permet de faire une action quand il est appelé. Et l'action c'est donc de récupérer de l'objet de contrôle les éléments dont il a besoin.

    Et au final l'objet de contrôle, quand tout a été saisi, s'occupe alors de l'enregistrement de la saisie en bdd.
    Oui cela ressemble à ce que j'ai pu faire en JS, il faut que je réfléchisse à la question pour savoir jusqu'où on peut aller avec cette méthode...

    Sinon je pense aussi à ce qu'on a vu dans l'autre fil...

  9. #9
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,

    J'ai aussi vu une autre solution basée sur le principe mentionné par @fred1599 & @Sve@r (passage d'instance en argument) sauf que là la communication se fait dans les deux sens :

    classA.py
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from classB import ClassB
     
    class ClassA:
        def __init__(self, class_b: ClassB):
            self.ref_to_class_b = class_b
            self.data_in_classA = "Data in classA"
     
        def communicate_to_b(self):
            print("from ClassA to ClassB:", self.ref_to_class_b.data_in_classB)
            self.ref_to_class_b.method_in_classB()
     
        def method_in_classA(self):
            print("Method in ClassA")

    classB.py
    Code python : 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
    from typing import TYPE_CHECKING
     
    if TYPE_CHECKING:
        from classA import ClassA
     
     
    class ClassB:
        def __init__(self, class_a: "ClassA"):
            self.ref_to_class_a = class_a
            self.data_in_classB = "Data in classB"
     
        def communicate_to_a(self):
            print("from ClassB to ClassA:", self.ref_to_class_a.data_in_classA)
            self.ref_to_class_a.method_in_classA()
     
        def method_in_classB(self):
            print("Method in ClassB")

    main.py
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    from classA import ClassA
    from classB import ClassB
     
    a = ClassA(None)
    b = ClassB(a)
    a.ref_to_class_b = b  
     
    a.communicate_to_b()  # Communication de ClassA à ClassB
    b.communicate_to_a()  # Communication de ClassB à ClassA


    ---> L’inconvénient que je vois pour l'instant c'est qu'il me semble que cela deviendrait plus compliqué dans le cas où on aurait plus de deux class, plus il y a de class et plus cela devient compliqué...

    Pour ce cas j'ai trouvé une autre solution...


    PS : cette partie :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    from typing import TYPE_CHECKING
     
    if TYPE_CHECKING:
        from classA import ClassA

    C'est pour pouvoir indiquer le typage :"ClassA" (cf.ci-dessous) en évitant les imports circulaires...

    Sous VS Code j'obtiens une bonne assistance : autocomplétion, re-factoring, go to definition...

    Il faut mettre le type en string ("ClassA") :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class ClassB:
        def __init__(self, class_a: "ClassA"):

  10. #10
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 824
    Points : 7 120
    Points
    7 120
    Par défaut
    Je pense que le pattern qui se rapproche de ce que tu souhaites est le pattern Observer.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    L’inconvénient que je vois pour l'instant c'est qu'il me semble que cela deviendrait plus compliqué dans le cas où on aurait plus de deux class, plus il y a de class et plus cela devient compliqué...
    C'est une généralisation/extension du pattern observer (dont on a déjà parlé) qui s'appelle publish-subscribe.
    Ils donnent en référence la bibliothèque externe pypubsub avec un cas d'utilisation (dans la documentation) qui mérite d'être lue.


    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  12. #12
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 105
    Points : 4 455
    Points
    4 455
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    cela deviendrait plus compliqué
    Il faudrait déjà savoir quelle est ta véritable demande !

    Si tu désires une "super" architecture: il faut déjà vouloir tout jeter (sauf formules mathématiques)
    Créer des architectures est un gros savoir : cela demande autant de temps que d'apprendre python (minimum: SOLID et design pattern). Donc vouloir le faire immédiatement sur ton projet en cours n'a pas de sens.
    Entre architecture/étude, codage, tests-debug, on arrive souvent à des ordres de grandeur du type 30% / 30% / 30%. Es-tu prêt à grandement retarder (encore ton projet) ? À repartir de zéro ?

    Utiliser une bonne architecture, avec les bons principes, c'est un code au départ bien plus compliqué (longuement pensé dès le départ). L'intérêt est surtout pour partager son code avec une équipe (pas ton cas) et pour avoir une maintenance plus simple à long terme (tu comptes encore retravailler sur ton projet dans 1..3 ans ?)

    ps: ne pas confondre avec "bien ranger ces fichiers dans une arborescence fichier", cela n'est pas lié au code.

    Note: on trouve énormément de documentation sur le web puisque ce sujet est plus lié à la poo que à python et parce que l'objet n'est plus tout jeune.
    $moi= ( !== ) ? : ;

  13. #13
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Salut,

    Citation Envoyé par fred1599 Voir le message
    Je pense que le pattern qui se rapproche de ce que tu souhaites est le pattern Observer.
    Citation Envoyé par wiztricks Voir le message
    C'est une généralisation/extension du pattern observer (dont on a déjà parlé) qui s'appelle publish-subscribe.
    Ils donnent en référence la bibliothèque externe pypubsub avec un cas d'utilisation (dans la documentation) qui mérite d'être lue.
    Merci à vous deux. J'ai commencé à regarder, il faut que j’approfondisse... Il me semble que cela ressemble aux slots/signaux déjà évoqués sauf que là ce n'est pas propre à Qt...

    Citation Envoyé par papajoker Voir le message
    Il faudrait déjà savoir quelle est ta véritable demande !
    Ben c'est simple, je pensais même que c'était un problème classique, répandu et auquel beaucoup ont déjà eu à faire...

    Comme expliqué au premier message :

    On a une interface graphique dans laquelle il y a plein d'onglets (frames) et même des fenêtres enfants...

    Chacun d'eux contient des champs de saisi, des boutons...

    Il y a par exemple des méthodes qui sont exécutées chaque fois qu'une donnée est saisie, par exemple pour mettre à jour les autres champs, pour tracer les courbes en fonction des nouveaux paramètres...

    Le problème c'est que les class (pour chaque onglet) peuvent dépendre les unes des autres mais que je voudrais quand même séparer le code dans différents fichiers...

    Alors par exemple on peut saisir des nouveaux paramètres dans l'onglet 1 et alors l'onglet 2 doit être mis à jour automatiquement (question de cohérence). Et cela peut aller dans les deux sens...

    Voilà restons sur cet exemple simple alors ma question c'est comment ce problème est résolu en général ?

    Parmi vous il doit y en avoir qui ont déjà eu à faire ça ou bien à répondre à quelqu'un qui eu à faire ça, non ? Ou bien ça n'arrive jamais ?

    ---> Pour l'instant il y a la solution du pattern observer et aussi la solution dont j'ai donné un exemple au message #9 (je ne sais pas ce qu'elle vaut mais j'ai une variante qui me semble meilleure...)


    Citation Envoyé par papajoker Voir le message
    Si tu désires une "super" architecture: il faut déjà vouloir tout jeter (sauf formules mathématiques)
    Créer des architectures est un gros savoir : cela demande autant de temps que d'apprendre python (minimum: SOLID et design pattern). Donc vouloir le faire immédiatement sur ton projet en cours n'a pas de sens.
    Non effectivement je ne cherche pas à faire une "super" architecture mais juste à faire ce qui est souvent conseillé, à juste titre selon moi, à savoir organiser/structurer son code (fonctions/class, modules, packages...).

    C'est plus facile de s'y retrouver, si j'ai un problème ou si je veux mettre à jour une fonctionnalité, c'est plus facile de trouver le bon module que de chercher la partie du code qui nous intéresse parmi des milliers de ligne contenus dans un seul fichier...

    Et il y a aussi la réutilisation des modules dans d'autres projets...

    Citation Envoyé par papajoker Voir le message
    ps: ne pas confondre avec "bien ranger ces fichiers dans une arborescence fichier", cela n'est pas lié au code.
    Oui mais si les codes contenus dans ces fichiers dépendent les uns des autres, il faudra bien faire quelque chose, non ?


    Citation Envoyé par papajoker Voir le message
    Utiliser une bonne architecture, avec les bons principes, c'est un code au départ bien plus compliqué (longuement pensé dès le départ). L'intérêt est surtout pour partager son code avec une équipe (pas ton cas) et pour avoir une maintenance plus simple à long terme (tu comptes encore retravailler sur ton projet dans 1..3 ans ?)
    Oui c'est vrai, je pourrais me passer d'une bonne architecture d'ailleurs comme je disais pour l'instant je bricole comme je peux...

  14. #14
    Membre expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 873
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 873
    Points : 3 717
    Points
    3 717
    Par défaut
    Pour l'instant il y a la solution du pattern observer que j’espère approfondir plus tard et il y a aussi la solution dont j'ai donné un exemple au message #9 , je ne sais pas ce qu'elle vaut mais j'ai une variante qui me semble meilleure et j'aimerais savoir ce que vous en pensez...

    Cette "solution" me semble meilleure que l'autre (du message #9) surtout dans le cas où on a plus de deux class...

    Une chose que j'apprécie c'est que sous VS Code j'obtiens une bonne assistance : autocomplétion, re-factoring, go to definition... Et la coloration syntaxique indique tout de suite si un attribut ou une méthode n'existe pas dans la class...

    Voici un exemple avec trois class (la communication peut faire dans tous les sens) :

    main.py
    Code python : 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
    from classA import ClassA
    from classB import ClassB
    from classC import ClassC
     
    class ClassABC:
     
        def __init__(self):
            self.a = ClassA(self)
            self.b = ClassB(self)
            self.c = ClassC(self)
     
     
    abc = ClassABC()
     
    abc.a.communicate_to_b()
    abc.a.communicate_to_c()
     
    abc.b.communicate_to_a()
    abc.b.communicate_to_c()
     
    abc.c.communicate_to_a()
    abc.c.communicate_to_b()

    classA.py
    Code python : 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
    from typing import TYPE_CHECKING
     
    if TYPE_CHECKING:
        from main import ClassABC
     
     
    class ClassA:
        def __init__(self, class_abc: "ClassABC"):
            self.class_abc = class_abc
            self.data_in_classA = "Data in classA"
     
        def method_in_classA(self):
            print("Method in ClassA")
     
        def communicate_to_b(self):
            print("\nfrom ClassA to ClassB:", self.class_abc.b.data_in_classB)
            self.class_abc.b.method_in_classB()
     
        def communicate_to_c(self):
            print("\nfrom ClassA to ClassC:", self.class_abc.c.data_in_ClassC)
            self.class_abc.c.method_in_ClassC()

    classB.py
    Code python : 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
    from typing import TYPE_CHECKING
     
    if TYPE_CHECKING:
        from main import ClassABC
     
     
    class ClassB:
        def __init__(self, class_abc: "ClassABC"):
            self.class_abc = class_abc
            self.data_in_classB = "Data in classB"
     
        def method_in_classB(self):
            print("Method in ClassB")
     
        def communicate_to_a(self):
            print("\nfrom ClassB to ClassA:", self.class_abc.a.data_in_classA)
            self.class_abc.a.method_in_classA()
     
        def communicate_to_c(self):
            print("\nfrom ClassB to ClassC:", self.class_abc.c.data_in_ClassC)
            self.class_abc.c.method_in_ClassC()


    classC.py
    Code python : 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
    from typing import TYPE_CHECKING
     
    if TYPE_CHECKING:
        from main import ClassABC
     
     
    class ClassC:
        def __init__(self, class_abc: "ClassABC"):
            self.class_abc = class_abc
            self.data_in_ClassC = "Data in ClassC"
     
        def method_in_ClassC(self):
            print("Method in ClassC")
     
        def communicate_to_a(self):
            print("\nfrom ClassC to ClassA:", self.class_abc.a.data_in_classA)
            self.class_abc.a.method_in_classA()
     
        def communicate_to_b(self):
            print("\nfrom ClassC to ClassB:", self.class_abc.b.data_in_classB)
            self.class_abc.b.method_in_classB()

  15. #15
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 105
    Points : 4 455
    Points
    4 455
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Alors par exemple on peut saisir des nouveaux paramètres dans l'onglet 1 et alors l'onglet 2 doit être mis à jour automatiquement (question de cohérence). Et cela peut aller dans les deux sens...
    Voilà restons sur cet exemple simple alors ma question c'est comment ce problème est résolu en général ?

    Parmi vous il doit y en avoir qui ont déjà eu à faire ça ou bien à répondre à quelqu'un qui eu à faire ça, non ? Ou bien ça n'arrive jamais ?
    Mais puisque tu ne nous donnes rien de ton code, on n'a aucune idée de ton véritable problème.

    Un exemple...
    Tu peux créer une structure complexe formulaires pour sauvegarder ton formulaire (utiliser une class perso est la bonne façon !). Dans cette structure, tu peux y mettre tes "Entry" et, éventuellement, si il y a un besoin mettre des StringVar (c'est mon exemple ici)
    Ici, l'onglet de résultats ne fait que lire en entrée notre structure complexe qui peut être complètement différente de l'interface graphique (pas dans cet exemple).

    Note: il n'y a rien d'objet dans cet exemple Il faut bien que tu travailles un minimum.
    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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    #!/usr/bin/env python
     
    import tkinter as tk                    
    from tkinter import ttk
    from collections import defaultdict
     
     
    root = tk.Tk()
    root.title("formulaire dans plusieurs onglets")
    root.geometry("500x200")
    tabControl = ttk.Notebook(root)
     
     
     
    tabin = ttk.Frame(tabControl)
    tabinbis = ttk.Frame(tabControl)
    tab_result = ttk.Frame(tabControl)
     
    tabControl.add(tabin, text ='Entrées 1')
    tabControl.add(tabinbis, text ='Entrées 2')
    tabControl.add(tab_result, text ='Résultat')
    tabControl.pack(expand = 1, fill ="both")
     
     
    # l'app utilise "que" cette structure pour faire le travail (le modèle)
    formulaires = defaultdict(dict)
    formulaires["tabin"]["nom"]= tk.StringVar()
    formulaires["tabin"]["age"]= tk.StringVar()
    formulaires["tabinbis"]["ville"] = tk.StringVar()
    formulaires["tabinbis"]["cp"] = tk.StringVar()
    formulaires["tab_result"]["calcul"] = tk.StringVar()  # graphique, ...
     
     
    ttk.Label(tabin, text = "Nom et prénom").grid(row = 0, column = 0)
    ttk.Label(tabin, text = "Age").grid(row = 1, column = 0)
    ttk.Entry(tabin, textvariable=formulaires["tabin"]["nom"]).grid(row = 0, column = 1)
    ttk.Entry(tabin, textvariable=formulaires["tabin"]["age"]).grid(row = 1, column = 1)
     
     
    ttk.Label(tabinbis, text = "Ville").grid(row = 0, column = 0)
    ttk.Label(tabinbis, text = "Cp").grid(row = 1, column = 0)
    ttk.Label(tabinbis, text = "voir onglet 1 (nom)").grid(row = 2, column = 0)
    ttk.Entry(tabinbis, textvariable=formulaires["tabinbis"]["ville"]).grid(row = 0, column = 1)
    ttk.Entry(tabinbis, textvariable=formulaires["tabinbis"]["cp"]).grid(row = 1, column = 1)
    ttk.Entry(tabinbis, textvariable=formulaires["tabin"]["nom"]).grid(row = 2, column = 1)
     
     
    tk.Label(tab_result, textvariable=formulaires["tabin"]["nom"]).grid(column=0, row=1, columnspan=2)
    tk.Label(tab_result, textvariable=formulaires["tabin"]["age"]).grid(column=0, row=2, columnspan=2)
    tk.Label(tab_result, textvariable=formulaires["tabinbis"]["ville"]).grid(column=0, row=3, columnspan=2)
    tk.Label(tab_result, textvariable=formulaires["tabinbis"]["cp"]).grid(column=0, row=4, columnspan=2)
    tk.Label(tab_result, textvariable=formulaires["tab_result"]["calcul"], text="En attente de données...").grid(column=0, row=5, columnspan=2)
     
     
    def on_tab_change(event):
        #global label_result  # juste pour démo
        tab = event.widget.tab('current')['text']
        print("actualiser", tab)
        if tab == "Résultat":
            print("Actualisation de cet onglet")
            print("refaire les calculs pour les afficher dans cet onglet")
            try:
                calcul = int(formulaires["tabinbis"]["cp"].get()) * int(formulaires["tabin"]["age"].get())
            except ValueError as err:
                calcul = "manque une entrée ?" + str(err)
            # NORMALEMENT calcul = Formulaires.generer_resultat()
            formulaires["tab_result"]["calcul"].set("résultat est ??? " + str(calcul))
     
        else:
            print("refaire aussi les calculs ? (si ils sont en cache ou sous-calculs)")
    tabControl.bind('<<NotebookTabChanged>>', on_tab_change)
     
     
    root.mainloop()
    En poo, puisque formulaires ne contient que des widget ou StringVar, ce n'est qu'une interface entre ta gui et ta classe métier qui fait les calculs/valide les entrées.

    La gui ne connait que l'interface formulaires et le code métier lui aussi ne connait que l'interface formulaires (que la gui soit écrite en poo ou pas ne change rien)
    L'interface formulaires n'a qu'une seule responsabilité : assurer un flux dans les 2 sens. Jamais elle ne valide un champ ! elle transmet la demande au "métier" et transmet la réponse à la gui. (donc mon exemple de code en l'état actuel est très très mauvais )
    $moi= ( !== ) ? : ;

  16. #16
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Alors par exemple on peut saisir des nouveaux paramètres dans l'onglet 1 et alors l'onglet 2 doit être mis à jour automatiquement (question de cohérence). Et cela peut aller dans les deux sens...
    Petite subtilité (j'en ai parlé mais je le redis): sous Qt tu as la méthode "showEvent()" automatiquement appelée quand un widget (donc un onglet) s'affiche.
    Donc l'onglet 2 tu ne le mets pas à jour quand l'onglet 1 fait sa saisie (faisable mais trop casse c... surtout s'il faut le faire sur 10 onglets) mais quand il est affiché. Et là ce n'est pas pareil.
    Donc quand un onglet X s'affiche il va chercher les données enregistrées par les autres onglets.

    Citation Envoyé par Beginner. Voir le message
    Oui mais si les codes contenus dans ces fichiers dépendent les uns des autres, il faudra bien faire quelque chose, non ?
    Un code Y ne dépend pas d'un code X. Un code est fait pour traiter des données. Donc X enregistre les données et Y les traite. Ou Y enregistre les données et X les traite.
    Et comme c'est séquentiel (je présume que tu n'es pas en prog parallèle) tout marche parfaitement.
    PS: le verbe "enregistrer" est à prendre au sens large (enregistrer dans un fichier, en bdd ou même en RAM)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  17. #17
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 824
    Points : 7 120
    Points
    7 120
    Par défaut
    Hello,

    @Beginner,

    La manière dont tu as développé classA, B et C et ABC ne correspondent pas à un pattern Observer.

    Pour modéliser un peu,
    1. Tes onglets seront chacun composés d'un observateur (on pourrait même dire que chacun de tes onglets est un observateur). Perso je préfère la composition...
    2. Ton interface composée de tes onglets sera également composée d'un notificateur (gestionnaire des observateurs).
    3. L'observateur envoi des messages, signaux, ... lors de la mise à jour ou d'un mouvement quelconque de tes onglets (à mon sens, la création d'un observateur pourrait prendre comme paramètre un callback).
    4. Le notificateur va notifier l'interface (application) en envoyant tous les messages, signaux, ... écoutés par tes observateurs.


    Maintenant j'ai quelques questions,


    1. Qu'est-ce qui justifie la création d'une classe par onglet ? (Y a-t-il tellement d'actions liées à un onglet ?)
    2. Quels sont les signaux que peuvent bien envoyer un onglet ? (Si peu de complexité dans les messages, signaux, est-ce que ça nécessite un pattern Oberver ?)
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  18. #18
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 105
    Points : 4 455
    Points
    4 455
    Par défaut
    Donc quand un onglet X s'affiche il va chercher les données enregistrées par les autres onglets.
    ici c'est un problème de design ui et nous n'avons aucune demande précise @Beginner

    Avec mon exemple donné plus haut #15:
    - On peut considérer que nous avons un unique formulaire "logique" réparti sur 36 onglets
    Le composant logique a en interne une structure du type form["champ_nom"] et une seule méthode self.validate().

    - On peut considérer que nous avons un formulaire par onglet (bouton valider dans chaque onglet)
    Le composant logique a en interne une structure du type form["onglet_nom"]["champ_nom"] et une méthode self.validate("onglet_nom").

    - On peut considérer que nous avons x formulaires par onglet (bouton valider dans chaque "frame")
    Le composant logique a en interne une structure du type form["onglet_nom"]["frame_nom"]["champ_nom"] et une méthode self.validate("onglet_nom", "frame_nom").

    Donc quel que soit le besoin, la logique/structure de base reste la même.
    Et nous pouvons, si besoin et si la gui le permet techniquement, toujours avoir une méthode pour valider un seul champ dans notre composant logique.

    Le retour de la méthode "Formulaires".validate() pourrait être du type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    err = formulaire.validate()
    if err:
        activer_onglet(err.onglet)
        dialog_erreur(err.onglet, f"{err.champ} non valide ! {err.message}")
    est-ce que ça nécessite un pattern Oberver ?
    Perso, je pense plus à un problème x y ...
    $moi= ( !== ) ? : ;

  19. #19
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    870
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 870
    Points : 1 522
    Points
    1 522
    Billets dans le blog
    4
    Par défaut
    Bonjour,
    Citation Envoyé par Beginner. Voir le message
    Ah il y a une solution avec Qt... C'est donc que cela ne doit pas être aussi simple qu'on pourrait le croire...

    Bon ben ça me rassure quelque part...
    ...Avec Kivy, le pattern observer se fait avec classe EventDispatcher .
    Perso, je ne l'utilise pas et n'en ai jamais encore éprouvé le besoin . De plus, j'us lu un avis qui mentionnait que l'usage pouvait rendre difficile à détecter et à suivre un bug ...
    Est ce vraiment de bonne pratique?
    Citation Envoyé par zen
    Explicit is better than implicit.
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Developpement pour Android avec Python3/Kivy/Buildozer

  20. #20
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par papajoker Voir le message
    Donc quel que soit le besoin, la logique/structure de base reste la même.
    Ce qui n'est pas moins important non plus est de constater qu'on peut aussi y "classer" des bouts dans le Model, d'autres dans Views, ... retrouver le pattern observer dans les Variable TK,... Inutile d'avoir une classification nommée Model/View/... pour n epas y retrouver tout ou partie des rôles/responsabilités de...

    Le pouvoir de ces abstractions est d'aider à "penser" ces rôles/responsabilités à l'écriture/lecture d'un code où on va s'appuyer sur les fonctionnalités natives du GUI pour les réaliser "avec" (plutôt qu'à côté).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Persistance et organisation du code
    Par K-Kaï dans le forum Hibernate
    Réponses: 16
    Dernier message: 06/06/2007, 17h01
  2. Organisation du code source
    Par _kal_ dans le forum C
    Réponses: 18
    Dernier message: 04/08/2006, 14h15
  3. organisation du code.
    Par poporiding dans le forum C++
    Réponses: 36
    Dernier message: 13/07/2006, 10h15
  4. organisation du code.
    Par poporiding dans le forum C++
    Réponses: 3
    Dernier message: 28/06/2006, 17h10
  5. Réponses: 4
    Dernier message: 19/09/2005, 17h56

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