36 votes

Comment mettre à jour l'ancien code C?

J'ai travaillé près de 10 ans de code C dans mon travail cette semaine, et après la mise en œuvre de quelques changements, je suis allé au patron et a demandé s'il avait besoin de rien d'autre. C'est quand il a laissé tomber la bombe. Ma prochaine tâche était de passer par l'7000 lignes et de comprendre plus de code, et à modulariser le code un peu. Je lui ai demandé comment il aimerait que le code source modulaire, et il m'a dit de commencer à mettre de l'ancien code C dans des classes C++.

Être un bon travailleur, je hochais la tête oui, et je suis retourné à mon bureau, où je suis assis maintenant, vous vous demandez comment dans le monde à faire ce code, et "modulariser" il. Il est déjà 20 fichiers source, chacun avec son propre but et la fonction. En outre, il y a trois "principaux" des structures. chacune de ces structures a plus de 30 domaines, beaucoup d'entre eux étant d'autres, plus petites structures. C'est un désordre complet pour essayer de comprendre, mais presque chaque fonction dans le programme est passé d'un pointeur sur l'un de leurs structures et utilise la structure fortement.

Est-il un moyen propre pour moi au chausse-pied en cours? Je suis résolu à le faire si cela peut être fait, je n'ai aucune idée de comment commencer.

35voto

John Points 336

Tout d'abord, vous avez de la chance d'avoir un patron qui reconnaît que le code refactoring peut être un long terme de la stratégie de réduction des coûts.

Je l'ai fait à de nombreuses reprises, qui est, conversion de l'ancien code de C à C++. Les prestations peuvent vous surprendre. Le code final peut être la moitié de la taille d'origine lorsque vous avez terminé, et beaucoup plus simple à lire. De Plus, vous aurez probablement découvrir délicate C bugs sur le chemin. Voici les étapes que je prendrais dans votre cas. De petites étapes sont importantes parce que vous ne pouvez pas sauter de A à Z lors d'un refactoring d'un grand corps de code. Vous devez aller par petites étapes intermédiaires qui ne peuvent jamais être déployé, mais qui peut être validé et étiquetés en quelque RCS vous utilisez.

  1. Créer une régression/suite de tests. Vous pourrez exécuter la suite de tests à chaque fois que vous terminez un lot de modifications au code. Vous devriez vous en avez déjà un, et il sera utile pour plus que juste ce refactoring tâche. Prendre le temps pour le rendre complet. L'exercice de la création de la suite de test permettra de vous familiariser avec le code.
  2. La direction du projet dans votre système de contrôle des révisions de choix. Armé avec une suite de tests de jeux et de direction, vous serez habilité à faire de grandes modifications au code. Vous ne serez pas peur de casser quelques œufs.
  3. Faire ces struct champs privés. Cette étape nécessite que très peu de modifications de code, mais peut avoir un grand profit. Passez un champ à la fois. Essayez de faire chaque champ private (oui, ou protégé), puis isoler le code d'accès à ce domaine. Le plus simple, la plupart des non-intrusive de conversion serait de rendre le code un friend function. Pensez également à des décisions que le code d'une méthode. La conversion du code d'une méthode est simple, mais vous aurez à convertir tous les sites d'appel ainsi. On n'est pas nécessairement meilleure que l'autre.
  4. Affiner les paramètres de chaque fonction. Il est peu probable que toute fonction nécessite un accès à toutes 30 les champs de la structure passée en argument. Au lieu de passer l'ensemble de la structure, ne laisser passer que les composants nécessaires. Si une fonction n'a, en fait, semblent exiger l'accès à de nombreux domaines différents de la structure, alors c'est peut-être un bon candidat pour être converti à une méthode d'instance.
  5. Const-identifier le nombre des variables, des paramètres et des méthodes que possible. Beaucoup de vieux code C ne parvient pas à utiliser const - le généreusement. Le balayage de bas en haut (en bas du graphe d'appel, qui est), vous pourrez ajouter plus de garanties pour le code, et vous serez en mesure d'identifier les mutateurs de la non-mutateurs.
  6. Remplacer les pointeurs avec des références où sensée. Le but de cette étape n'a rien à voir avec le fait d'être plus similaire à C++juste pour le plaisir d'être plus similaire à C++. Le but est d'identifier les paramètres qui ne sont jamais NULL et qui ne peut jamais être ré-attribuée. Pensez à une référence au moment de la compilation de l'assertion qui dit, c'est un alias vers un objet valide et représente le même objet tout au long de l'étendue actuelle.
  7. Remplacer char* avec std::string. Cette étape devrait être évident. Vous pouvez réduire considérablement les lignes de code. De Plus, il est amusant de remplacer 10 lignes de code avec une seule ligne. Parfois, vous pouvez éliminer l'ensemble des fonctions dont le but était de réaliser C de la chaîne des opérations qui sont standard en C++.
  8. Convertir C des tableaux d' std::vector ou std::array. Encore une fois, cette étape devrait être évident. Cette conversion est beaucoup plus simple que la conversion de l' char de std::string parce que les interfaces d' std::vector et std::array sont conçus pour correspondre à la C la syntaxe de tableau. L'un des avantages est que vous pouvez éliminer que les extra - length variable transmise à chaque fonction à côté de la matrice.
  9. Convertir malloc/free de new/delete. Le principal objectif de cette étape est de préparer le futur de refactoring. Changer simplement le code C à partir d' malloc de new n'est pas directement le gain de beaucoup. Cette conversion permet d'ajouter des constructeurs et des destructeurs de ces structures, et de l'utilisation intégrée en C++ automatique de la mémoire d'outils.
  10. Remplacer localiser new/delete opérations avec la std::auto_ptr de la famille. Le but de cette étape est de rendre votre code d'exception-safe.
  11. Lancer des exceptions où les codes de retour sont traitées par bouillonner jusqu'. Si le code C gère les erreurs en vérifiant spécial les codes d'erreur de retourner le code d'erreur à son appelant, et ainsi de suite, entrer le code d'erreur à l'appel de la chaîne, alors que le code C est probablement un candidat pour l'utilisation des exceptions à la place. Cette conversion est en fait triviale. Simplement, throw le code de retour (C++ vous permet de lancer n'importe quel type que vous voulez) au niveau le plus bas. Insérer un try{} catch(){} déclaration à l'endroit dans le code qui gère l'erreur. Si aucun endroit approprié existe pour gérer l'erreur, il est recommandé de mettre le corps de l' main() en try{} catch(){} déclaration et d'enregistrement.

Maintenant du recul et de regarder combien vous avez amélioré le code, sans les convertir en quelque chose de classes. (Oui, oui, techniquement, votre les structures sont des classes déjà.) Mais vous n'avez pas rayer la surface de l' OO, encore réussi à grandement simplifier et de consolider le code en C d'origine.

Devriez-vous convertir le code à utiliser des classes, avec le polymorphisme et l'héritage graphique? Je n'en dis pas. Le code C n'est probablement pas avoir une conception globale qui se prête à une OO modèle. Notez que le but de chaque étape ci-dessus n'a rien à voir avec l'injection OO principes dans votre code C. L'objectif était d'améliorer le code existant par l'application de la autant de la compilation des contraintes de temps que possible, et en éliminant ou en simplifiant le code.

Une étape finale.

Envisager d'ajouter des repères de sorte que vous pouvez montrer à votre patron lorsque vous avez terminé. Pas seulement de critères de performance. Comparer les lignes de code, l'utilisation de la mémoire, nombre de fonctions, etc.

19voto

omermuhammed Points 5468

Cette transition en C ++ semble être arbitraire. Demandez à votre supérieur hiérarchique s'il en a besoin. Déterminez si vous pouvez atteindre le même objectif moins péniblement, voyez si vous pouvez prototyper un sous-ensemble de la nouvelle manière moins pénible, puis allez faire une démonstration. patron et vous recommandons de suivre le chemin le moins pénible.

11voto

David Relihan Points 3719

Tout d'abord, dites à votre patron que vous n'êtes pas continuer jusqu'à ce que vous avez:

http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672

et, dans une moindre mesure:

http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052

Deuxièmement, il n'existe aucun moyen de modularising code par chaussure-horning en C++ de la classe. C'est une tâche énorme et vous avez besoin de communiquer la complexité de refactoring très proceedural code à votre patron.

Il se résume à faire un petit changement (extrait de la méthode, la méthode de déplacement de classe, etc...), puis de le tester - il n'y a pas de raccourci avec cette.

Je ne ressens votre douleur si...

5voto

pcent Points 976

Je pense qu'une meilleure approche pourrait consister à réécrire totalement le code, mais vous devriez demander à votre chef dans quel but il souhaite que vous " commenciez à mettre l'ancien code C dans des classes c ++ ". Vous devriez demander plus de détails

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X