web-dev-qa-db-fra.com

Principes de conception, meilleures pratiques et modèles de conception pour C (ou programmation procédurale en général)?

Existe-t-il des principes de conception, des meilleures pratiques et des modèles de conception connus que l'on peut suivre lors de la conception d'un projet C? Ou des principes de conception utiles pour la programmation procédurale (impérative) en général?

(Je suis enfant de la 'génération orientée objet' et dois concevoir un grand projet C pour la première fois)

90
Dimi

Masquage des informations - comme le préconise Parnas ( Software Fundamentals ).

Gestion soigneuse des en-têtes et visibilité:

  • Tout dans un fichier source qui peut être caché du monde extérieur devrait l'être; seule l'interface externe documentée doit être exposée.
  • Tout ce qui est exposé est déclaré dans un en-tête.
  • Cet en-tête est utilisé là où la fonctionnalité est nécessaire (et où elle est définie).
  • L'en-tête est autonome - lorsque vous en avez besoin, vous l'utilisez et vous n'avez pas à vous inquiéter de `` quels autres en-têtes dois-je également inclure '' car l'en-tête garantit qu'il fonctionne en incluant tout ce dont il a besoin pour le faire travail.
  • L'en-tête est auto-protégé - il n'a donc pas d'importance s'il est inclus plusieurs fois.

    #ifndef HEADER_H_INCLUDED
    #define HEADER_H_INCLUDED
    ...rest of header contents, including other #include lines if necessary
    #endif /* HEADER_H_INCLUDED */
    
  • Concevez des ensembles de fonctions pour travailler sur des "objets" (généralement des structures) - et utilisez ces fonctions plutôt que de fouiner les entrailles de la structure dans le code qui l'utilise. Considérez-le comme une encapsulation auto-imposée.

62
Jonathan Leffler

Il existe un bon livre en ligne gratuit, intitulé Programmation orientée objet avec ANSI-C , qui couvre le sujet de écrire du code orienté objet en C. A recherche Google pour "C orienté objet" donne également un certain nombre d'autres bons exemples et ressources.

Si votre projet est critique pour la sécurité, MISRA-C est un bon ensemble de règles. Il est principalement destiné au c intégré, mais il peut également être utile dans d'autres domaines.

Je me considère comme un codeur OO, et je travaille beaucoup avec Embedded-C. Le meilleur conseil que je puisse donner, en particulier pour les grands projets, est de ne pas en faire trop. Créer un = complet OO framework au-dessus d'ANSI C peut être très tentant, mais cela prend beaucoup de temps et d'efforts pour bien faire les choses. Plus vous êtes amateur, plus vous passez de temps à déboguer votre framework à la place de travailler sur le projet réel . Approchez la tâche avec la tête claire et une bonne compréhension solide de YAGNI . Bonne chance!

22
e.James

Mes trois conseils:

  • Écrire des tests unitaires. Ils vous aideront à vous concentrer sur une conception adaptée à votre problème au fur et à mesure. Bien mieux que de s'appuyer (uniquement) sur une pensée préméditée.
  • Avoir un détecteur de fuite de mémoire (il existe toutes sortes de bibliothèques) installé et opérationnel dès le premier jour. Demandez à cette bibliothèque d'imprimer toutes les fuites dès la fin du programme/des tests. Cela vous permettra d'attraper une fuite dès que vous l'introduirez, ce qui rendra sa fixation beaucoup moins douloureuse.
  • Ecrire OOP code en C. Pas si difficile. Bien qu'il soit possible d'émuler la méthode de remplacement, je vous suggère de commencer par l'émulation d'objets simples. Même ce mécanisme simple peut vous donner un grand kilométrage.

Voici un exemple:

typedef struct Vector {
  int size;
  int limit;
  int* ints; 
} Vector;

Vector* Vector_new() {
  Vector* res = (Vector*) malloc(sizeof(Vector));
  res->limit = 10;
  res->size = 0;
  res->ints = (int*) malloc(sizeof(int) * res.limit);

  return res;
}


void Vector_destroy(Vector* v) {
  free(v->ints);
  free(v);
}

void Vector_add(Vector* v, int n) {
  if(v->size == v->limit) {
    v->limit = v->limit * 2 + 10;
    v->ints = realloc(v->ints, v->limit);     
  }

  v->ints[v->size] = n;
  ++v->size;
}

int Vector_get(Vector* v, int index) {
  if(index >= 0 && index < v->size)
    return v->ints[index];

  assert false;
}
21
Itay Maman

La POO est une méthodologie et non une technologie. Donc, mon premier conseil est d'arrêter de le considérer comme une programmation procédurale.

Pour faire valoir e.James, vous ne voulez pas essayer de recréer un langage orienté objet ou prétendre que vous en avez les capacités. Vous pouvez toujours faire toutes les bonnes choses en vous accrochant à quelques principes simples:

  1. Testez tout.
  2. Trouvez ce qui varie et encapsulez-le.
  3. Conception aux interfaces.
7
MaxGuernseyIII

La norme de codage SEI CERT C fournit n bon ensemble de règles et de bonnes pratiques courantes ainsi que des choses que vous devriez essayer d'éviter d'utiliser.

4
Rami