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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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++.
-
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.
-
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.
-
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.
-
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.