1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mars 2013
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mars 2013
    Messages : 45
    Points : 25
    Points
    25

    Par défaut fonction privée/public (modèle MVC)

    Bonjour (ou bonsoir),


    J'essaie tant bien que mal de comprendre comment rendre une fonction privée.
    Je sais qu'il n'y a pas de privé/public en C, et qu'il faut passer par la déclaration "static" d'une fonction pour limiter sa portée au fichier dans laquelle elle est exécutée.


    Je me suis lancé dans la réalisation d'un programme qui imite le fonctionnement d'une application de messagerie (type Msn Messenger, ou SMS) en essayant de respecter le modèle MVC, le tout via des listes chainée (User -> contact -> msg)

    Donc, je suis parti sur l'idée de considérer mon main comme un prg externe qui fait appel a une sorte d'API que mon controller fourni au main pour exécuter certaines fonctions de base : ajout, effacer, sélectionner, afficher (des user, contact ou msg).

    J'ai bien compris comment déclarer une fonction static dans mon fichier "controller.c" et comment y faire appel depuis mon main.c
    Je déclare et définis d'abord une fonction en static dans le controller.c, ensuite je définis une fonction "normal" dans le controller (que je déclare dans controller.h que j'inclus dans le main) qui fait appel a la fonction static définis précédemment.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // main.c
    #include "controller.h"
     
    foo();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // controller.h
     
    int foo(void);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // controller.c
     
    static fooStatic();
    {
    ...
    }
     
    foo()
    {
    fooStatic();
    }

    Jusque la tout va bien, mais comment je fais si je veux que la fonction fooStatic() soit dans déclarée et définie dans un autre fichier que le controller.c, par exemple dans model.c ou vue.c??
    Lors de mes test, ça ne fonctionne pas.. ou alors je dois passer à nouveau par une couche supplémentaire.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // main.c
    #include "controller.h"
     
    foo();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // controller.h
     
    int foo(void);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    // controller.c
    #include "modele.h"
     
    foo()
    {
    fooModele();
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // modele.h
     
    fooModele(void);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    // modele.c
     
    staticFooModele(void)
    {
    ...
    }
     
     
    fooModele()
    {
    staticFooModele();
    }

    Est ce que j'ai bon?? Est ce que c'est la seule manière de faire?? Est ce que ça n'est pas trop tortueux??
    En fait, ce dont je veux être sûr, c'est de respecter le modèle MVC au plus près en respectant la séparation des différents module du MVC et la notion "privée" des fonctions qui seront appelée par chacun de ces modules. (??)

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    5 027
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : juin 2007
    Messages : 5 027
    Points : 16 828
    Points
    16 828

    Par défaut

    Tu peux faire une solution intermédiaire.

    Soit une fonction disponible pour un module donnée (mettons module1).

    Tu pourrais avoir un en-tête privé de module1, genre module1_internals.h, qui déclare cette fonction.
    Seul ce module s'en sert.
    Comme la fonction s'appellerait module1_internal_f(), elle ne risque pas d'entrer en collision de nom avec les autres modules.


    Mieux, encore, pour renforcer la chose. Tu pourrais placer ce module1_internals.h dans un dossier dédié au module 1.
    Ainsi, lorsque tu compiles les fichiers du module1, tu ajoute ce dossier dans les chemins d'inclusions, et pas celui des autres modules.
    Un bon choix de ce dossier, ce serait en sous dossier, du dossier de sources.

    Par exemple src/module1/include.

    En fait, comme si tu compilais des bibliothèques distinctes pour chaque module.
    Idéalement, ton code devrait le permettre.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    2 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 2 196
    Points : 4 872
    Points
    4 872

    Par défaut

    Pour rejoindre ternel , pour simuler l'encapsulation, je passe par 2 entêtes : XXX.h et XXX_private.h.
    Avec comme conditions :
    • XXX_private.h fait un include de XXX.h
    • XXX.h est donnée au client et contient toutes les fonctions/ déclarations publiques
    • XXX_private.h est utilisée seulement par le module/ la bibliothèque


    Et comme le dit ternel [en général] 1 module/ bibliothèque == 1 dossier, sans parler de la structure de ton projet.
    Parce que ce dossier peut se trouver dans le dossier threads/ devices/ utils/ ... et ce dernier lui même se trouver dans le dossier sources/ sources_C/ libraries/ ... [et ainsi de suite]

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mars 2013
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mars 2013
    Messages : 45
    Points : 25
    Points
    25

    Par défaut

    Merci pour vos réponses..
    Mais je ne comprend pas bien..

    Mon but est "d'offrir" 4 fonctions au main.
    Est ce que le simple fait de faire comme vous dites et d'inclure les .h l'un dans l'autre suffit a empêcher le main de faire appel au fonctions que je vais déclarer dans le .h qui contiendra l'include?

    Pour ce qui est des dossiers.. la aussi je ne comprend pas bien.. j'ai mis en plus une structure de dossier, mais plus par facilité de m'y retrouver dans mon code que pour exercer une quelconque séparation..

    Est ce que vous pourriez etre plus imagé si possible svp??
    Ou m'indiquer des fichiers source ou je pourrais aller voir comment "ils" ont fait?

    Peut etre le plus simple serait de vous montrer le schéma (très simple) que j'ai fait de mon applicaton(?!)
    https://www.lucidchart.com/invitatio...4-6f2e7040c216

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mars 2013
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mars 2013
    Messages : 45
    Points : 25
    Points
    25

    Par défaut

    Après qlq tests, je n'arrive pas à comprendre comment la portée des fonctions déclarées dans un autre fichier fonctionne.

    Dans mon test très simple, je n'ai même pas besoin d'inclure le fichier controller.h, dans lequel je n'ai de toute façon rien déclaré (sauf l'enum).. et le test fonctionne quand même !!?
    (Je suis sous visual studio 2017)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    // main.c
     
    #include
     
    int main(int argc, char *argv[])
    {
     
    	printf("getConfig 0	: %d\n", getConfig());
    	printf("setConfig       : %d\n", setConfig());
    	printf("getConfig 1	: %d\n", getConfig());
     
    	return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    //controller.h
     
    enum
    {
    	IS_NOT_INIT,
    	Is_INIT
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    // controller.c
     
    #include "controller.h"
     
     
    static int MSG_isInit = IS_NOT_INIT;
     
     
     
    int getConfig()
    {
    	return MSG_isInit;
    }
     
     
    int setConfig()
    {
    	return MSG_isInit = Is_INIT;
    }

    Je ne comprend pas comment c'est possible.. et surtout, je ne comprend pas comment faire pour empêcher le main de "voir" les fonctions définie dans controller.c du coup.
    La seule chose qui fonctionne, c'est de passer par un artifice comme je l'ai fait dans le premier post.

    ??

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    5 027
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : juin 2007
    Messages : 5 027
    Points : 16 828
    Points
    16 828

    Par défaut

    Une fonction n'est utilisable que si elle est déclarée dans l'unité de compilation en cours.
    L'unité de compilation, c'est l'espèce de fichier obtenue une fois exécuté le préprocesseur. C'est-à-dire, quand on a entre autre remplacé les #include par le contenu des fichiers inclus.

    ton main ne peut pas utiliser getConfig(), car la fonction n'est déclarée nulle part.
    Il faut la déclaration (le prototype) dans le .h.

    Cela dit, ca, c'est la théorie, car il s'agit de l'application du C moderne vu par la norme.

    Ton compilateur est peut-être extrèmement laxiste, et applique encore la très vieille possibilité du C d'avant sa normalisation, à savoir la "int simulated declaration".

    Toute fonction non déclarée est supposée déclarée comme int bidule(), c'est à dire retournant un int, et prenant une liste non spécifiée d'arguments.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    mars 2013
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : mars 2013
    Messages : 45
    Points : 25
    Points
    25

    Par défaut

    Citation Envoyé par ternel Voir le message
    Une fonction n'est utilisable que si elle est déclarée dans l'unité de compilation en cours.
    L'unité de compilation, c'est l'espèce de fichier obtenue une fois exécuté le préprocesseur. C'est-à-dire, quand on a entre autre remplacé les #include par le contenu des fichiers inclus.

    ton main ne peut pas utiliser getConfig(), car la fonction n'est déclarée nulle part.
    Il faut la déclaration (le prototype) dans le .h.

    Cela dit, ca, c'est la théorie, car il s'agit de l'application du C moderne vu par la norme.

    Ton compilateur est peut-être extrèmement laxiste, et applique encore la très vieille possibilité du C d'avant sa normalisation, à savoir la "int simulated declaration".

    Toute fonction non déclarée est supposée déclarée comme int bidule(), c'est à dire retournant un int, et prenant une liste non spécifiée d'arguments.
    Ok, ca je peux comprendre..

    Je suppose qu'il doit y avoir des options pour forcer visual studio à respecter "la norme"??!


    Donc, si je comprend les post précédents

    Je dois passer par une structure de fichiers ce type la (??)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    // main.c
     
    #include api.h
     
    foo();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    // api.h
     
    void foo(void);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    // controller.h
     
    #include api.h
     
    void fooController(void);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // api.c
     
    #include controller.h
     
    void foo(void)
    {
    fooController();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // controller.c
     
    #include controller.h
     
    void fooController(void)
    {
    ...
    }

Discussions similaires

  1. jsf et le modèle MVC
    Par mjihanne dans le forum JSF
    Réponses: 11
    Dernier message: 21/03/2008, 14h01
  2. Questions sur le modèle MVC
    Par dr23fr dans le forum Développement Web en Java
    Réponses: 3
    Dernier message: 05/12/2006, 20h46
  3. Interface SWT selon le modèle MVC
    Par LoloBebop dans le forum SWT/JFace
    Réponses: 6
    Dernier message: 05/07/2006, 17h27
  4. [Architecture] Comment s'approcher du modèle mvc ?
    Par nikalkal dans le forum EDI/Outils
    Réponses: 4
    Dernier message: 21/06/2006, 18h46
  5. Architecture J2EE et modèle MVC
    Par alexd dans le forum Développement Web en Java
    Réponses: 4
    Dernier message: 23/02/2005, 16h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo