Je trouve que chaque fois que je travaille avec du code GUI, le code a tendance à gonfler plus rapidement que les autres types de code. Il semble également plus difficile de refactoriser. Alors que dans d'autres types de code, je peux refactoriser assez facilement - je trouve que je peux décomposer une classe plus grande en fonctionnalités plus petites - avec la plupart des frameworks d'interface graphique, je suis souvent lié à un framework qui requiert mon widget / control / toute classe pour implémenter beaucoup plus de choses plus directement dans le widget / contrôle / que ce soit. Parfois, cela est dû à la nécessité de (a) hériter d'un widget / contrôle / chose de base ou (b) d'accéder à des méthodes protégées.
Je dois aussi généralement, par exemple, répondre à une grande variété d'entrées via des signaux / événements / quel que soit le cadre pour implémenter tous les modes d'interaction avec l'utilisateur. Je pourrais avoir besoin dans un widget / contrôle d'interface graphique pour gérer une grande variété d'entrées / sorties pouvant inclure:
- un clic droit / menu contextuel
- réagir aux sélections du menu contextuel - qui peuvent être nombreuses
- un moyen spécial de peindre l'interface graphique
- réagir à la saisie au clavier
- boutons, cases à cocher,
- etc
... tout en gérant les classes sous l'interface graphique représentant la logique métier.
Une interface graphique simple et simple peut faire croître son code assez rapidement, même en séparant la logique de commerce et en utilisant MVC, je trouve que le code d'interface graphique est un puissant aimant pour le changement.
Existe-t-il un moyen de gérer le code de l'interface graphique de manière saine et d'éviter de le laisser devenir une fenêtre cassée? Ou une masse de gestionnaires d'événements aléatoires / méthodes surchargées est-elle vraiment la meilleure solution pour le code d'interface graphique?
la source
Réponses:
Ce qu'il faut retenir du code d'interface graphique, c'est qu'il est piloté par les événements et que le code piloté par les événements aura toujours l'apparence d'une masse de gestionnaires d'événements organisés de manière aléatoire. Cela devient vraiment désordonné lorsque vous essayez d'introduire du code non événementiel dans la classe. Bien sûr, il a l’apparence de fournir un support pour les gestionnaires d’événements et vous pouvez garder vos gestionnaires d’événements sympas et petits, mais tout ce code de support supplémentaire flottant rend votre source d’interface graphique apparemment gonflée et désordonnée.
Alors, que pouvez-vous faire à ce sujet et comment rendre les choses plus faciles à refactoriser? Eh bien, je changerais d'abord ma définition du refactoring de quelque chose que je fais occasionnellement à quelque chose que je fais continuellement pendant que je code. Pourquoi? Parce que vous souhaitez que le refactoring vous permette de modifier votre code plus facilement, et non l'inverse. Je ne vous demande pas simplement de changer la sémantique ici, mais plutôt de faire un peu de gymnastique mentale afin de voir votre code différemment.
Les trois techniques de refactoring que j’utilise le plus souvent sont Rename , Extract Method et Extract Class . Si je n'avais jamais appris un autre refactoring, ces trois me permettraient toujours de garder mon code propre et bien structuré, et d'après le contenu de votre question, il me semble que vous allez probablement vous retrouver à utiliser les trois mêmes refactorings presque constamment garder votre code graphique mince et propre.
Vous pouvez obtenir la meilleure séparation possible entre la GUI et la logique métier dans le monde, mais le code de la GUI peut sembler comme si une mine de code avait explosé au milieu de celle-ci. Mon conseil est qu'il ne fait pas mal d'avoir une classe supplémentaire ou deux pour vous aider à gérer votre interface graphique correctement, et cela ne doit pas nécessairement être vos classes View si vous appliquez le modèle MVC - bien que vous trouviez souvent les classes intermédiaires sont si semblables à votre vision que vous ressentirez souvent le besoin de les fusionner pour plus de commodité. Mon point de vue est qu’il n’est pas très utile d’ajouter une couche supplémentaire spécifique à l’interface graphique pour gérer toute la logique visuelle, mais vous voudrez probablement en peser les avantages et les coûts.
Mon conseil est donc:
la source
Je pense que bon nombre des problèmes que vous rencontrez peuvent être imputés à une cause simple. La plupart des développeurs ne traitent pas le code d'interface graphique comme un code «réel». Je n'ai aucune preuve ou statistique ici, juste mon instinct.
Peut-être pensent-ils qu'il ne s'agit que d'une présentation et n'est pas important. " Il n'y a pas de logique commerciale ", disent-ils, " pourquoi l'unité le teste "? Ils rient lorsque vous parlez de l'orientation des objets et de l'écriture de code propre. Ils n'essayent même pas d'améliorer les choses. Il n'y a pas de structure pour commencer, ils tapent simplement du code et le laissent pourrir tandis que d'autres ajoutent leur propre contact au fil du temps. Un beau bordel, un code graffiti.
Le code d'interface graphique a ses propres défis, il doit donc être traité différemment et avec respect. Il a besoin d'amour et de développeurs qui veulent l' écrire. Ceux qui vont le garder mince et lui donner une bonne structure et des modèles corrects.
la source
Pour une raison quelconque, le code d'interface graphique crée un angle mort chez les développeurs concernant la séparation des préoccupations. C'est peut-être parce que tous les tutoriels regroupent tout dans une classe. C'est peut-être parce que la représentation physique fait en sorte que les choses semblent plus étroitement couplées qu'elles ne le sont. Peut-être est-ce dû au fait que les classes se construisent lentement afin que les gens ne se rendent pas compte qu'ils ont besoin d'une refactorisation, comme si on faisait bouillir la grenouille proverbiale en augmentant lentement la chaleur.
Quelle que soit la raison, la solution consiste à rendre vos cours beaucoup plus petits. Je le fais en me demandant continuellement s'il est possible de mettre ce que je tape dans une classe séparée. S'il est possible de mettre dans une autre classe, et je peux penser à un nom simple et raisonnable pour cette classe, alors je le fais.
la source
Vous voudrez peut-être jeter un coup d'œil au motif Présentation de vue modèle / Vue passive. Ray Ryan a donné une bonne conférence sur un IO Google concernant les meilleures pratiques d’architecture pour GWT.
http://www.google.com/events/io/2009/sessions/GoogleWebToolkitBestPractices.html
Il est facile d’abstraire les idées dans d’autres cadres et langues. Le principal avantage de MVP (à mon avis) est la testabilité unitaire. Et vous n’obtenez que cela, si votre code n’est pas gonflé et pas spaghetti (à en juger par votre question, c’est ce que vous voulez). Cela fonctionne en introduisant une couche logique de vue appelée le présentateur. La vue réelle en est découplée via une interface (et peut donc être facilement simulée lors de tests unitaires). Maintenant, puisque votre couche logique de vue (le présentateur) est libérée des éléments internes de la structure d'interface graphique concrète, vous pouvez l'organiser comme du code standard et vous n'êtes pas lié, par exemple, à la hiérarchie d'héritage Swings. Idéalement, vous pouvez basculer les implémentations d'interface graphique dans différents frameworks, à condition qu'ils soient conformes à la même interface.
la source
Ma réponse comprend quatre parties: structure, simplicité, tests et syntaxe.
Les trois premiers sont vraiment difficiles à faire!
Structure signifie accorder une attention particulière à l'utilisation du moins de code possible et du maximum de frameworks, de bibliothèques, etc.
La simplicité signifie garder les choses simples, de la conception initiale à la mise en œuvre réelle. Garder la navigation simple, utiliser des plugins simples, garder la mise en page assez "simple" aidera tous ici. Elles peuvent maintenant être «vendues» à des clients / utilisateurs qui peuvent rapidement voir les avantages des pages fonctionnant sur des ordinateurs, des ipad, des appareils mobiles et autres.
Les moyens de test incluent des outils de test de navigateur (webrat et capybara me viennent à l’esprit avec mon travail sur les rails) qui détectent les problèmes inter-navigateurs dès le début, alors qu’il est possible de concevoir un meilleur code pour les traiter au début, par opposition aux «correctifs» fréquents du code. par différents développeurs car ils sont "découverts" par les utilisateurs de différents navigateurs.
Syntaxe. Il est vraiment utile d’utiliser un vérificateur de code / IDE / éditeur-plugin, etc. pour vos langages HTML, CSS, Javascript, etc. Un outil qui vérifie votre format HTML est donc essentiel. Avoir du HTML bien formé est très utile pour avoir du HTML sans fioritures car un mauvais code devrait avoir plus de visibilité.
la source
La solution que j'ai trouvée est un code déclaratif. Utiliser uniquement du code de procédure est une recette pour le code d'interface graphique spaghetti. Bien sûr, une "manière spéciale de peindre le widget" restera probablement du code. Mais c'est du code isolé dans une classe. Gestionnaires d'événements, raccourcis clavier, tailles de fenêtres - tout ce qui est en désordre est mieux déclaré.
la source
Il y a beaucoup de bonnes réponses ici.
Une chose qui m'a aidé à simplifier le code de l'interface graphique est de m'assurer que celle-ci dispose de son propre modèle de données.
Pour prendre un exemple simple, si j’ai une interface graphique avec 4 champs de saisie de texte, j’ai une classe de données distincte qui conserve le contenu de ces 4 champs de saisie de texte. Les interfaces graphiques plus complexes nécessitent davantage de classes de données.
Je conçois une interface graphique comme un modèle - vue. Le modèle d'interface graphique est contrôlé par le contrôleur d'application du modèle d'application - view - controller. La vue de l'application correspond au modèle d'interface graphique plutôt qu'au code de l'interface graphique elle-même.
la source
Les applications telles que le traitement de texte, les éditeurs graphiques, etc. ont des interfaces complexes et leur code ne peut être simple. Cependant, pour les applications métier, l'interface graphique n'a pas besoin d'être aussi complexe, mais elle l'est toujours.
Certaines des clés de la simplification de l'interface graphique sont (la plupart s'appliquent à .NET):
Efforcez-vous de conception plus simple chaque fois que possible. Évitez les comportements fantaisistes s'ils ne sont pas demandés par l'entreprise.
Utilisez un bon fournisseur de contrôles.
Ne créez pas de fonctionnalité de contrôle personnalisé dans le code client même. Créez plutôt des contrôles utilisateur qui étendent le contrôle d'origine de sorte que vous puissiez refléter vos comportements spécifiques dans les contrôles plutôt que dans le code du formulaire / de la page utilisant.
Utilisez un cadre (même développé localement) pour gérer l’internationalisation, la gestion des ressources, les styles, etc. afin de ne pas répéter ce code dans chaque interface utilisateur.
Employer un composant (ou un framework) pour la navigation.
Construire des dialogues standard pour les erreurs, les avertissements, les confirmations, etc.
la source
Appliquez la conception orientée objet à votre code et pour le développement d'interface utilisateur:
Voici une application petite mais non-triviale pour aider à illustrer certains de mes points. Vous pouvez trouver le diagramme d'interaction code et vue / modèle ici: https://github.com/vanfrankie/pushpopbox
la source
Vous voulez jeter un oeil sur le concept de "liaison de données" . C'est un moyen de connecter les éléments de l'interface utilisateur aux éléments de modèle abstraits de manière déclarative, de sorte que les éléments de modèle soient automatiquement synchronisés avec le contenu de l'interface utilisateur. Cette approche présente de nombreux avantages, par exemple le fait de ne pas avoir à écrire les gestionnaires d’événements vous-même pour synchroniser les données.
Il existe un support de liaison de données pour de nombreux frameworks d'interface utilisateur, par exemple .NET et Eclipse / JFace .
la source