Dans nos applications pour la plupart volumineuses, nous n'avons généralement que quelques emplacements pour les "constantes":
Les constantes sont généralement séparées en différentes structures dans ces classes. Dans nos applications C++, les constantes ne sont définies que dans le fichier .h et les valeurs sont affectées dans le fichier .cpp.
L'un des avantages est que toutes les chaînes, etc. sont au même endroit et que tout le monde sait où les trouver quand quelque chose doit être changé.
C'est particulièrement quelque chose que les chefs de projet semblent aimer quand les gens vont et viennent et de cette façon, tout le monde peut changer des choses aussi triviales sans avoir à fouiller dans la structure de l'application.
En outre, vous pouvez facilement changer le titre de zones de groupe/onglets similaires, etc. à la fois. Un autre aspect est que vous pouvez simplement imprimer cette classe et la donner à un non-programmeur qui peut vérifier si les légendes sont intuitives et si les messages à l'utilisateur sont trop détaillés ou trop confus, etc.
Cependant, je vois certains inconvénients:
Où stockeriez-vous des constantes comme ça? Quels arguments apporteriez-vous également pour convaincre votre chef de projet qu'il existe de meilleurs concepts qui répondent également aux avantages énumérés ci-dessus?
N'hésitez pas à donner une réponse spécifique ou indépendante en C++.
PS: Je sais que cette question est un peu subjective mais honnêtement, je ne connais pas de meilleur endroit que ce site pour ce genre de question.
J'ai des nouvelles sur la chose du temps de compilation:
Suite aux messages de Caleb et de gbjbaanb, j'ai divisé mon fichier de constantes en plusieurs autres fichiers quand j'ai eu le temps. J'ai également finalement divisé mon projet en plusieurs bibliothèques, ce qui était désormais beaucoup plus facile. La compilation en mode de publication a montré que le fichier généré automatiquement qui contient les définitions de la base de données (table, noms de colonne et plus - plus de 8000 symboles) et accumule certains hachages a causé les énormes temps de compilation en mode de publication.
Désactiver l'optimiseur de MSVC pour la bibliothèque qui contient les constantes DB nous a maintenant permis de réduire le temps total de compilation de votre projet (plusieurs applications) en mode release à partir de à 8 heures à moins d'une heure!
Nous n'avons pas encore découvert pourquoi MSVC a tant de mal à optimiser ces fichiers, mais pour l'instant, ce changement soulage beaucoup de pression car nous n'avons plus à nous fier uniquement aux versions nocturnes.
Ce fait - et d'autres avantages, comme un couplage moins serré, une meilleure réutilisation, etc. - ont également montré que passer du temps à diviser les "constantes" n'était pas une si mauvaise idée après tout ;-)
Étant donné que cette question reçoit toujours une certaine attention:
Voici ce que j'ai fait ces dernières années:
Mettez chaque constante, variable, etc. exactement dans la portée qui lui convient: Si vous utilisez une constante uniquement dans une seule méthode, il est OK de la définir dans cette méthode. Si une seule classe est intéressée, laissez-la comme détail d'implémentation privée de cette classe. Il en va de même pour l'espace de noms, le module, le projet, la portée de l'entreprise. J'utilise également le même modèle pour les fonctions d'assistance et similaires. (Cela peut ne pas s'appliquer à 100% si vous développez un cadre public.)
Cela augmente la réutilisabilité, la testabilité et la maintenabilité à un degré où vous passez non seulement moins de temps à compiler (au moins en C++), mais aussi moins de temps à corriger les bogues, ce qui vous laisse plus de temps pour développer réellement de nouvelles fonctionnalités. Dans le même temps, le développement de ces fonctionnalités ira plus vite car vous pouvez réutiliser plus de code plus facilement. Cela l'emporte sur tout avantage que le fichier de constantes centrales pourrait avoir d'une ampleur.
Jetez un œil en particulier au Principe de Ségrégation d'Interface et au Principe de Responsabilité Unique si vous voulez en savoir plus.
Si vous êtes d'accord, la réponse de Caleb à la hausse depuis cette mise à jour est essentiellement une interprétation plus générale de ce qu'il a dit.
Les constantes spécifiques à une classe doivent aller dans l'interface de cette classe.
Les constantes qui sont vraiment des options de configuration doivent faire partie d'une classe de configuration. Si vous fournissez des accesseurs pour les options de configuration de cette classe (et les utilisez à la place des constantes ailleurs), vous n'aurez pas à recompiler le monde entier lorsque vous modifiez quelques options.
Les constantes qui sont partagées entre les classes mais qui ne sont pas censées être configurables doivent avoir une portée raisonnable - essayez de les décomposer en fichiers qui ont des utilisations particulières afin que les classes individuelles incluent uniquement ce dont elles ont réellement besoin. Cela contribuera à nouveau à réduire les temps de compilation lorsque vous modifiez certaines de ces constantes.
Je dirais simplement que vous voulez diviser votre énorme classe de constantes en plusieurs fichiers plus petits, un par formulaire par exemple. Cela garantit que vous n'avez pas une telle dépendance énorme sur le fichier de constantes, donc ajouter ou mettre à jour une chaîne ne nécessiterait pas alors une recompilation totale. Vous pouvez toujours stocker ces fichiers dans un emplacement central, mais (par exemple) avoir 1 fichier avec des constantes pour chaque boîte de dialogue, convenablement nommé. Ensuite, vous ne pouvez inclure ces fichiers que dans les fichiers de dialogue appropriés, ce qui réduit considérablement la recompilation.
Je vous suggère également d'utiliser quelque chose comme GNU GetText utilitaires pour gérer les chaînes, il est conçu pour la traduction, mais fonctionne tout aussi bien pour simplement changer le texte en quelque chose d'autre. Vous pouvez les mettre dans une ressource de chaînes, mais je trouve qu'elles sont plus difficiles à utiliser car elles sont saisies par ID, les utilitaires GetText sont saisis par une chaîne d'origine - rend les choses très faciles à développer.
Remarque: je ne suis pas un développeur C++ ... mais voici ma pensée: vous devez envisager de suivre le commentaire de @ jk sur la différence entre l'utilisation des fichiers de configuration. Dans DotNet, il existe un fichier de ressources utilisé pour stocker ces informations. Dans Windows Forms, un fichier de ressources est conservé à partir de VS pour chaque formulaire.
Je ne vois pas de valeur pour une constante à placer en dehors de son champ d'utilisation, sauf s'il s'agit d'une constante globale qui doit être partagée. Comme vous l'avez mentionné, cela sera au moins difficile à maintenir pendant le développement. En outre, vous pouvez rencontrer des conflits de noms. Une autre chose est qu'il peut être difficile de savoir qui utilise une constante donnée.
Maintenant, si vous souhaitez que les non-programmeurs examinent les informations, pour l'interface graphique, vous capturez l'écran pour eux. Si vous souhaitez qu'ils examinent les entrées du tableau de données, vous pouvez exporter les données vers Excel ou quelque chose de similaire.
Si vous souhaitez toujours utiliser une approche de localisation centralisée et que vous souhaitez placer toutes vos constantes dans un seul gros fichier, chaque développeur peut utiliser un fichier partagé qui est mis à jour à la fin de chaque intervalle dans un fichier central. Les données proviendront de fichiers individuels utilisés dans le développement. Cela peut être facilement automatisé ou effectué manuellement. Cependant, comme je l'ai dit, c'est probablement un risque que vous n'avez pas à prendre.
Il n'y a pas de solution générale. Renseignez-vous sur les performances, la convivialité, la sécurité et le cycle de vie d'une constante.
Plus ils sont proches de leur portée, plus les performances sont élevées.
Plus ils sont regroupés logiquement et hors de leur portée, plus la réutilisation est élevée.
Moins les costants sont accessibles, plus la sécurité est élevée.
Plus la durée de vie d'une constante est élevée, moins elle se soucie de l'endroit où vous la mettez pour la facilité d'utilisation.
Une constante comme un numéro de version sera définie dans une sorte de manifeste. Un code d'erreur d'une fonction d'erreur sera défini à l'intérieur de la classe. Le code d'erreur est probablement quelque chose avec une durée de vie élevée (= ne change presque jamais). Le mettre dans un fichier constant ne fait que spammer le fichier avec des trucs inutiles.
Moins la constante a le caractère d'une constante mais d'une variable (comme le numéro de version), plus vous pouvez la mettre à l'extérieur. Moins la constante est variable, plus elle est constante, plus elle doit être placée à l'intérieur de sa portée. Pendant le débogage, il est judicieux de le placer à l'extérieur pour réduire le temps de compilation.
Cependant, votre problème initial est le temps de compilation. La question est donc de savoir si vous posez la bonne question. Si le temps de compilation de votre application est trop élevé, vous devriez mieux penser à un moyen de le rendre plus modulaire afin que les pièces fonctionnent indépendamment les unes des autres. Compilez-le partiellement et testez vos trucs indépendamment. Si vos tests unitaires sont correctement effectués et à fond (ce qui représente en fait beaucoup de travail), vous pouvez facilement déplacer des éléments sans avoir à vous en soucier. Et puis la question devient totalement différente.
Je suggérerais de mettre toutes ces constantes dans une sorte de fichier de configuration. Pour les applications Java, nous utilisons généralement des fichiers .properties, un texte simple avec chaque ligne formatée comme "(clé) = (valeur)". Exemple
MainPanel.Title = Bienvenue dans notre application DB.table.users = TBL_USERS Logging.filename = application.log
Vous chargez ensuite ce fichier au moment de l'exécution, remplissez un cache qui vous permet de rechercher une clé et de récupérer une valeur. Lorsque vous avez besoin d'une constante, vous interrogez le cache. Vous aurez toujours besoin d'avoir vos clés quelque part et le cache devra être accessible globalement, mais lorsque vous modifiez les valeurs réelles des constantes, non recompiler est nécessaire, il devrait être possible de simplement redémarrer l'application (ou si vous voulez vraiment avoir de la fantaisie, avoir plusieurs fichiers .properties et caches et donner à l'application la possibilité de recharger un cache au moment de l'exécution).
Pour une implémentation, j'ai trouvé ceci SO question: https://stackoverflow.com/questions/874052/properties-file-library-for-c-or-c = (c'était le premier hit sur une recherche Google - je n'ai pas utilisé ce logiciel moi-même).