8
votes

Comment structurer correctement les projets OOP et multifile?

En tant que programmeur débutant, apprenez maintenant les bases de l'OOP, j'ai rencontré de nombreux problèmes avec la structure d'inclusion de base de mes programmes de pratique. Je me suis enseigné en tant que programmation en utilisant diverses ressources écrites et en ligne. Mais voici mon problème (Eh bien, l'un d'entre eux ...):

D'une part, Je comprends l'importance de l'abstraction, de l'encapsulation et d'avoir un faible degré d'accouplement entre les classes , pourtant, d'autre part, je me débats énormément avec Structuration de mon programme et concevoir mes classes d'une manière qui permet différentes classes dans différents fichiers de se connaître les unes des autres .

Bien sûr, il s'agit d'un problème majeur de la mine qui a abouti à un code pirateux bâclé qui ne fonctionne que sur la manière dont je veux que cela puisse jeter chaque directeur de base sur la fenêtre et commencez à remplir mon code avec des variables de globaux, en avant Déclarations de tout partout et faire des membres de la classe publique.

Mettez simplement: ma programmation est un désordre ... C ++ est mon premier langage de programmation, et même lorsque je fais de mon mieux pour concevoir / écrire dans un objet orienter, je me retrouve avec un Balade laid de fichiers, #incluant tout dans presque tous les fichiers et une combinaison étrange de code de la procédure et du spaghetti OOP qui fonctionne rarement!

Je suis un novice de programmation auto-proclamé, et j'accepte qu'il faut du temps pour apprendre à structurer un programme, mais je suis presque à la fin de Wind! Je sais que mon problème découle du fait que je connais un petit bit sur OOP. Je sais que je veux écrire des classes indépendantes qui gèrent une tâche unique. Mais dans le même temps, je ne comprends pas comment alerter correctement chaque classe de l'existence des autres parties du programme. C'est un peu comme sachant quels types de nourriture que vous devriez manger mais ne sachant pas comment utiliser une fourchette ...

C'est mon problème en un mot. Et pour suivre davantage quelques questions plus spécifiques que j'ai:

  • dans le projet multifile C ++, est-ce normal / nécessaire pour mettre la fonction principale () à l'intérieur d'une classe de ses propres? Ou est-ce la chose standard de laisser votre principale () dans la portée globale?

  • Dans les programmes de procédure précédents que j'ai écrits en C ++, il n'était pas rare d'avoir une variables de constantes ou #defines dans la portée globale, au sommet du fichier principal.cpp. Par exemple, peut-être que les dimensions de l'écran ou d'autres informations utiles seraient définies au début du programme. Que se passe-t-il dans OOP? Cette pratique est-elle complètement évitée? Ou est-ce que je fais un fichier main.h et #incluez-le dans tous les autres en-tête du projet? Je n'ai aucune idée de quoi faire à propos de ceci ...

  • Lorsque vous écrivez mon premier programme de PRATURE MOYENNE PRATIQUE, mon travail est arrivé à une halte à la crise lorsque j'ai commencé à essayer d'écrire une classe de statemachine. J'ai eu mon intention de disposer de la classe StateMachine contenir que tout l'écran possible indique que le programme utiliserait. Cependant, un problème est né de la situation où ma classe de statemachine ne semblait pas être au courant de certaines de mes autres classes d'État, même si elles étaient toutes #inclus. J'ai déjà vu des déclarations de classes avant, est-ce nécessaire? Devrais-je être spammer des déclarations de classes de classe partout ou est-ce une odeur de code?

  • Enfin, l'ordre de #include et les commandements de déclaration avancée sont-ils importants?

    Je sais que c'est probablement une question super fondamentale, mais c'est quelque chose qui m'a donné un temps vraiment difficile dans ma transition des programmes débutants de la procédure à un fichier unique à la programmation multi-fichiers. Existe-t-il une règle générale pour structurer vos programmes afin que tout fonctionne juste? J'utilise les gardes inclus, alors y a-t-il une raison pour laquelle on ne peut pas simplement utiliser chaque en-tête dans chaque fichier source? Devrais-je avoir un fichier commun.h qui est #include dans chaque fichier d'en-tête pour chaque classe?

    J'apprécie vraiment toute aide / conseil que la communauté peut me donner. Je sais que c'est un obstacle simple, mais important pour moi de passer avant de pouvoir commencer à développer mes compétences de l'OOP. J'essaie d'exercer d'exercer mon cerveau l'importance de garder les cours séparées les uns des autres au point où je ne suis pas sûr de la manière de configurer mes classes / fichiers de manière à leur permettre de vraiment interagir les uns avec les autres! Merci beaucoup pour l'aide!


3 commentaires

Pour une meilleure compréhension de OOP, pourquoi ne pas essayer de jouer avec Java ou C # ou même mieux python (imo, c'est le meilleur point d'essayer dans votre cas)? C ++ est l'une des langues les plus puissantes sans aucune question, mais c'est mal de tête (pour moi quand même) travaillant avec des classes en C ++


@Plb: i Recommandez sincèrement apprendre C ++ d'abord et "pure oo" / déchets collectés de langue seconde. Cela fait pour une fondation très solide, évite plusieurs arrestations d'erreurs de conception / de mise en œuvre et permet une transition beaucoup plus facile plus tard. Apprendre Java / C # / Python d'abord Afin de Learn C ++ seconde est une erreur définitive .


@DevSolar Je ne discute pas que l'apprentissage C ++ vous donne d'abord un grand avantage et mieux comprendre comment écrire un code efficace. Mais comme l'a mentionné l'OP, il possède une expérience de C ++ avec des codes de procédure. Il a en fait un problème de compréhension et / ou d'utilisation pratique des conceptions de OOP. Python / Java / C # pourrait lui donner une idée en quelques jours. Je ne suis pas très expérimenté, alors peut-être que je me trompe. C'est juste mon avis.


3 Réponses :


1
votes

OK ... Donc, le principal problème semble conserver une organisation OO de votre dossier. Tout d'abord, si vous n'avez pas lu la Guide de style Google C ++ Je vous conseillerais de manière robuste de le faire. J'ai aussi trouvé Cette réponse précédente plutôt claire et simple

J'espère que cette aide


1 commentaires

Bien qu'il y ait beaucoup de bonnes notes dans le Guide de style Google, il y en a aussi plusieurs soi-même, plus appropriés pour la ré-entraînement des développeurs Java, qui mettent un sertissage horrible dans un style C ++. Interstallation des exceptions, permettant aux paramètres de sortie, interdire les arguments par défaut, décourageant l'utilisation de bibliothèques de boost de C ++ 11 / "non approuvées", des trucs comme ça. C'est un guide de style pour Google Travail interne, pas vraiment générique «Meilleure pratique C ++».



4
votes

Vous ne pouvez pas penser à OOP comme une programmation fonctionnelle normale avec des classes. C'est une mauvaise approche et ça va vous induire en erreur.

Conception de l'architecture de votre application est extrêmement important, il existe des livres entiers écrits à ce sujet. Plus vous concevez la structure de votre application, plus ce sera plus facile pour vous de coder, et moins les erreurs que vous allez avoir. C'est un bon conseil d'apprendre les bases de certains langages de modélisation pour vous faciliter la dessin et la bien comprendre. UML est un excellent choix pour cela.

Il y a deux approches pour la conception de grandes choses. Vous pouvez descendre, ce qui signifie que vous commencez à un niveau élevé d'abstraction et descendez, réduisez vos problèmes. Ou vous pouvez monter, en commençant par la mise en œuvre de petites choses faciles à faire, puis monter, reliant Yuor de petits modules dans une application.

Vous pouvez facilement trouver beaucoup d'informations sur cela sur le Web. C'est en un mot. Maintenant, pour vos questions spécifiques.

  1. laisser le principal dans une portée globale. Personnellement, je le laisse même dans un fichier distinct.CPP pour le garder propre, mais cela ne compte pas où le mettez-vous.

  2. Essayez d'éviter les variables globales. Si vous avez besoin de constantes, il est correct de les définir. Et oui, votre approche avec toutes les définitions dans un seul fichier d'en-tête fonctionne bien. Toutefois, vous voudrez peut-être les séparer par signification, et non pour inclure un fichier avec 10000 définit dans une .CPP qui en a besoin d'une seule.

  3. Si vous avez besoin d'utiliser une classe avant qu'elle ne soit déclarée, vous devrez le déclarer - le déclarer, sinon le compilateur ne saura pas qu'il est là.

  4. L'ordre de l'inclut est important, car chaque #include Copypaste fondamentalement le texte du fichier correspondant. Donc, si vous #include Votre class.h Dans votre classe.cpp , le texte de l'en-tête ne sera que collé dans le fichier source par la préprocesseur. L'ordre de déclaration d'avenir n'a pas vraiment d'importance tant que vous déclarez déclarer des trucs avant de l'utiliser pour la première fois.


0 commentaires

4
votes
  • C ++ est plus que OOP, il est plusieurs paradigmes . N'essayez pas de tout appuyer sur le filtre OO, cela ne se déroule pas. À plusieurs endroits, C ++ peut faire des choses plus élégamment, car vous êtes pas limité à "pur" oo. Par exemple,

  • principal () est jamais à l'intérieur d'une classe et toujours à la portée mondiale.

  • Les règles les plus importantes sont "cohérence" et "maintenabilité". Pensez à la façon dont vous allez examiner le programme plus tard, une fois qu'il est «terminé» et que vous souhaitez réparer quelques bugs. Où trouverez-vous des constantes et définirez-vous le moyen le plus simple?

  • Si la séquence de #include intègre, vos fichiers d'en-tête sont cassés. Chaque en-tête devrait être (minimalement) autonome pour les choses déclarées dedans.

  • Déclaration de classe par en-tête, une définition d'une classe par unité de mise en œuvre. Les noms identiques du fichier et de la classe. Vraiment, il s'agit de la seule règle que je considère non négociable. Avoir à grep pour plus d'informations sur une classe est des commandes de grandeur plus gênantes que trouver ing.

    Le reste, vraiment, peut être trouvé dans tous les bons livres sur C ++, et vous devriez vraiment travailler avec un livre au lieu de vous enfiler sur des tutoriels et des pages de questions-réponses.


4 commentaires

Je sais ce que vous voulez dire, et je suis d'accord, mais la règle ne doit pas vraiment être une classe par fichier, mais plutôt un composant par fichier, avec le nom du fichier étant la classe principale (et donc le composant et la classe partageant le nom). Pourquoi cette distinction? La définition d'un type d'assistant (exemple: l'itérateur qui navigue sur le conteneur) doit être associé à la classe aidée (le conteneur). +1


@ Davidrodríguez-Dribesas: ACK pour les itérateurs, qui font une partie assez intégrale d'une classe. Mais beaucoup trop souvent, j'ai vu des classes "assistant" grandir au-delà de leur concept initial, utilisée partout (dans d'autres espaces de noms, même, intelligemment caché derrière un à l'aide d'un espace de noms déclaration) - et c'est putain agaçant d'avoir à les suivre en essayant de comprendre ce qu'ils sont en fait faire ...


Merci pour le conseil! Je suis toujours intéressé à apprendre des livres et des livres électroniques, et je possède déjà quelques-uns. L'effet secondaire malheureux d'enseigner vous-même est que vous n'avez pas de professeurs ou de pairs de rebondir des idées lorsque vous êtes coincé sur quelque chose, quelle que soit sa simplicité! Pour cette raison, j'apprécie vraiment l'aperçu des personnes sur ce site. Je prendrai certainement tous ces conseils et regarder mes diverses ressources à nouveau pour voir si je peux développer une meilleure compréhension de la structure du programme. Merci pour votre temps! :)


@MRKATSWORDFISH: Jetez un coup d'œil aux sources disponibles. Si vous les comprenez bien, notez ce qui les rend compréhensibles et tenter de l'imiter. Si vous rencontrez des problèmes, notez le «pourquoi» et l'éviter.