Bonjour,
Je travaille actuellement sur un projet en Python 3.5 et je m’interroge sur la manière d’organiser mon code.
Ma bibliothèque permet de gérer des projets, où un projet est simplement un ensemble de documents à éditer (des fichier odf par exemple) par le responsable de projet et permettant de générer des documents de rendu (des fichiers pdf, par exemple). Il est alors possible de :
- Télécharger des modèles de documents, à compléter ;
- Lire les documents (par exemple, avec LibreOffice) ;
- Mettre des documents (de sortie) en ligne (sur Google Drive par exemple) pour les sauvegarder et/ou les partager.
J’ai donc créé trois classes abstraites ainsi que des filles plus fonctionnelles :
1 2 3 4 5 6 7 8 9 10 | class DocumentReader: pass class DocumentDownloader: pass class DocumentUploader: pass # Mes documents sont au format ODF class LibreOfficeDocumentReader(DocumentReader): pass # Mes modèles sont sur un Drive class DriveDocumentDownloader(DocumentDownloader): pass # Je partage mes documents sur un Drive class DriveDocumentUploader(DocumentUploader): pass |
Un projet (classe Project
) est en particulier un DocumentReader
et possiblement un DocumentDownloader
et/ou DocumentUploadder
. Et là, j’ignore quelle API fournir, vu que je crois avoir plusieurs possibilités :
Héritage multiple
1 | class MyProject(LibreOfficeDocumentReader, DriveDocumentDownloader, DriveDocumentUploader): pass |
Seulement, j’obtiens un conflit d’attributs. Par exemple, DriveDocumentUploader
et DriveDocumentDownloader
ont toutes les deux un attribut drive
permettant de faire des requêtes à l’API GDrive sous un compte particulier. Mais la valeur diffère, parce que je ne télécharge pas les modèles à partir du même compte que celui sur lequel je sauvegarde les documents.
Bref, cette méthode d’héritage multiple me semble compromise.
Injection de dépendance
Une autre méthode consisterait à passer en paramètre de mon projet mes reader, downloader et uploader :
1 2 | class Project: def __init__(self, name, reader, downloader=None, uploader=None): pass |
Seulement, cela signifie que je ne peux pas faire my_project.my_reader_method()
(mais my_project.reader.my_reader_method()
), à moins d’ajouter dynamiquement à my_project
les méthodes du reader. Là encore, je risque de tomber sur des conflits au niveau des noms des méthodes du reader, downloader et uploader (en l’occurrence, il n’y en a pas, mais c’est plausible).
Conclusion
Après rélfexion, la seconde méthode dans sa première variante (my_project.reader.my_reader_method()
) me semble préférable, mais j’ignore si elle est pythonique, ou même juste judicieuse. Auriez-vous des conseils à ce sujet ?
Merci !