2010-01-23 6 views
1

J'ai souvent lu sur l'opportunité de scinder de gros blocs (monolithiques?) De code d'application en fichiers de code source distincts pour le rendre plus facile à entretenir, etc., mais je n'ai pas encore vu quoi que ce soit expliquant exactement comment faire cela. Le processus de création de fichiers séparés est assez simple lors de l'ajout d'une sous-classe bien sûr - et c'est un bon exemple de ce que j'essaie de réaliser - mais que faire si nous avons seulement un objet contrôleur et nous voulions diviser notre code en disant, (1) une interface et groupe de fichiers d'implémentation contenant seulement méthodes pour calculer des choses et (2) une autre paire contenant seulement méthodes d'impression, mais chaque méthode peut avoir accès à toutes les autres méthodes comme si ils étaient tous dans le fichier (source).Segmentation du code en plusieurs fichiers source

Des conseils détaillés sur la façon de procéder à ce sujet (si possible) seraient grandement appréciés. Merci :-)

Répondre

3

Ceci est mieux fait en utilisant des catégories. Par exemple, créer un fichier d'en-tête appelé MyController + Printing.h:

#import "MyController.h" 
@interface MyController (PrintingSupport) 
- (void)print:(id)sender; 
@end 

et le fichier de mise en œuvre MyController + Printing.m:

#import "MyController+Printing.h" 
@implementation MyController (PrintingSupport) 
- (void)print:(id)sender 
{ 
} 
@end 

Rechercher dans les fichiers d'en-tête d'Apple pour de grands exemples de cette technique.

+0

Merci beaucoup pour les extraits de code, Costique! Il me faudra un peu de temps pour étudier le code Apple (et lire aussi les 'catégories'), donc je ne pourrai pas l'essayer tout de suite, mais je devrais réussir à le finir ce week-end. Je reviendrai à vous alors. En attendant, merci encore pour votre aide :-) – Bender

+0

De rien. – Costique

1

Je ne connais pas ce langage de programmation, mais en général, le but de la modularisation est de cacher une implémentation complexe et d'exposer une interface simple. C'est bien, car vous n'avez généralement pas besoin de toutes vos données et de toutes vos fonctionnalités pour effectuer toutes les tâches. Ceci est fait en gardant les données proches de l'endroit où elles sont utilisées (par exemple la même classe), et en utilisant peu de méthodes publiques. Cependant, il existe des situations où vous devez prendre en charge le partage de nombreuses données et fonctionnalités entre les modules facilement, ce qui ressemble à ce que vous voulez faire. Par exemple. Dans la programmation GUI, le modèle de conception modèle-vue-contrôleur ne fait que cela. La clé est de regrouper vos données et fonctions d'une autre manière, mais il est beaucoup moins facile de bien faire. Plutôt que de séparer le contrôleur des données, est-il possible de refactoriser de sorte que chaque partie de données soit avec une partie correspondante du contrôleur? Par exemple, si vous avez deux types de données, pouvez-vous refactoriser en deux classes, chacune ayant des méthodes pour calculer et imprimer ce type de données? Peut-être que vous trouverez également que certaines des "données" sont en réalité l'état du contrôleur, et cela appartient définitivement au code du contrôleur.

+0

Bien que je n'ai jamais trouvé de page montrant * comment * modulariser, en cherchant des exemples sur la recommandation de Costique, ainsi que des exemples de catégorie, j'ai aussi trouvé la démo "SimpleCocoaApp" d'Apple où il utilise un contrôleur principal plus deux autres Objets NSObject auxquels sont assignées des tâches distinctes par l'objet contrôleur principal. C'est ce que tu veux dire? Est-ce que plusieurs objets personnalisés distincts sont considérés comme un gaspillage de ressources? Non? (Je demande par ignorance des débutants ici). Hmmm ... il semble maintenant qu'il y ait * plusieurs * solutions à ma question! Merci, abc. Appréciez votre aide :-) – Bender

+0

Ayant regardé le cacao, je comprends qu'il recommande/applique le modèle de conception MVC. 1) Oui, le contrôleur peut être divisé en une sorte de hiérarchie si ce n'est pas très bon. 2) Vous pouvez avoir de nombreux objets personnalisés, si chacun représente un concept unique (comprendre "concept" comme vous le souhaitez). Enfin, le but de MVC est de modulariser les données, tout en permettant à un contrôleur de faire des références croisées avec différents types de données facilement. Mon avis est que * seul * code qui fait cela devrait aller dans le contrôleur. Le code qui fait quelque chose avec un seul type de données (une classe de modèle) doit être dans cette classe de modèle. J'espère que cela pourra aider. – abc

+0

Cela aide certainement, et merci pour votre contribution. Je suppose que je me suis peinte dans un coin en me précipitant pour ajouter du code sans donner la priorité à une structure correctement planifiée * d'abord * (vous savez comment c'est :-)). J'ai maintenant un modèle (test) NSObject fonctionnant à côté de mon AppController et il fonctionne parfaitement - même si je vois ce que vous entendez par: "... grouper vos données et fonctions d'une autre manière, mais il est beaucoup moins facile de réussir.«Il y a certains objets communs (comme un tableau principal) qui doivent être transmis à différents contrôleurs de modèles, mais de manière générale, j'ai les bases maintenant .. Merci encore – Bender

2

Si vos classes sont si grandes que vous envisagez de les découper en fichiers source distincts, vous avez probablement un problème de conception.

Le modèle de conception modèle-vue-contrôleur (meilleur, modèle-contrôleur-vue) crée un petit code modulaire presque automatiquement.

Le modèle gère tout ce qui concerne les données. La vue gère l'interface utilisateur visuelle réelle et le contrôleur colle les deux ensemble. Chacun est une classe distincte et, idéalement, le modèle et la vue doivent être si indépendants qu'ils peuvent être facilement branchés dans une autre application.

La clé est d'être totalement impitoyable dans la fonction de séparation. Il est toujours tentant de parquer les données dans le contrôleur. Cela est particulièrement vrai lorsque vous apprenez et écrivez de petits programmes avec très peu de données. Cependant, à mesure que la complexité des données augmente, votre contrôleur explose rapidement avec la complexité.

Toute bonne conception commence par le modèle de données. Le modèle doit gérer toutes les relations logiques avec les données, c'est-à-dire créer, modifier, vérifier, enregistrer, etc. Un modèle de données correctement conçu est totalement indépendant de l'interface utilisateur. Idéalement, un modèle de données devrait fonctionner avec des vues standard, des vues Web, une ligne de commande ou une URL exportée.

Je commence toujours un projet en créant le modèle de données dans une application de test avec l'interface minimale absolue. (Souvent, il ne s'agit que d'une application vierge qui se lance, manipule par programmation le modèle de données, imprime vers la console et se ferme.) Ce n'est que lorsque le modèle de données fonctionne indépendamment que je me tourne vers le reste du programme.

Maintenant que je comprends les opérations de données et de données, je peux concevoir une interface utilisateur pour chaque environnement que je vais utiliser. L'interface utilisateur comprend uniquement comment créer des éléments d'interface utilisateur et comment réagir aux événements. Il ne contient aucune donnée ou même logique reliant les éléments les uns aux autres.

Le contrôleur colle la vue et le modèle de données ensemble. Le contrôleur ne sait que les messages à envoyer au modèle de données pour obtenir les données qui vont dans un élément d'interface utilisateur particulier en réponse à un événement particulier. Il ne valide pas les données et n'effectue aucune opération logique sur celles-ci. Il achemine simplement l'information entre le modèle de données et la vue du moment.

Toute opération, telle que l'impression, qui crée une autre interface doit avoir son propre objet contrôleur. Par exemple, lors de l'impression, seul le modèle de données comprend comment toutes les données s'emboîtent sur une page. Il n'y a aucune raison pour que le même contrôleur qui contrôle la vue de l'interface utilisateur contrôle l'impression. Au lieu de cela, un contrôleur d'impression demande simplement au modèle de données les données à imprimer. Le contrôleur de l'interface utilisateur n'a rien d'autre à faire que d'appeler le contrôleur d'impression et de le diriger vers les données sélectionnées par l'utilisateur. Dans votre exemple, les méthodes de calcul se trouvent dans le modèle de données, les méthodes d'impression dans un contrôleur d'impression, etc. Avec model-view-controller, vous obtenez de nombreuses classes modulaires étonnamment faciles à gérer , testé et porté.

+1

" Si vos classes grandissent, vous pensez à la façon dont Je suis d'accord 100%: en tant que débutant, j'avais tendance à ignorer tous les concepts ennuyeux de 'model-view-controller' et à écrire du code - et j'ai juste continué à ajouter des choses plus soignées à mes applications comme je suis tombé sur d'autres exemples de code (précédemment non découverts) Je vais devoir prendre un peu de temps pour réorganiser mon approche de base Merci pour le conseil judicieux TechZen.) – Bender