/** * Méthode appelée pour le calcul de la cohésion entre 2 fonctions. * * <p>Calcule le pourcentage de paramètres similaires entre les deux fonctions sur l'ensemble des * paramètres des deux fonctions. * * @param f1 Une fonction d'un modèle de code source * @param f2 Une autre fonction d'un modèle de code source * @return Un double entre 0.0 et 100.0 * @see #cohesion(Function, Function) */ private double cohesionArguments(Function f1, Function f2) { double result = 0.0; double nbCommon = 0; Set<LocalVariable> argsFct1 = f1.getArguments(); Set<LocalVariable> argsFct2 = f2.getArguments(); Set<LocalVariable> args = new HashSet<LocalVariable>(); for (LocalVariable arg1 : argsFct1) { for (LocalVariable arg2 : argsFct2) { if (arg1.getType().equals(arg2.getType())) { if (similarity.similar(arg1.getName(), arg2.getName())) { ++nbCommon; } } args.add(arg1); args.add(arg2); } } if (args.size() > 0) { result = 100.0 * nbCommon / args.size(); } return result; }
/** * Méthode appelée pour le calcul de la cohésion entre 2 fonctions. * * <p>Calcule le pourcentage de types utilisés en commun dans les deux fonctions sur le nombre * total de types utilisés dans les deux fonctions. * * @param f1 Une fonction d'un modèle de code source * @param f2 Une autre fonction d'un modèle de code source * @return Un double entre 0.0 et 100.0 * @see #cohesion(Function, Function) */ private double cohesionTypes(Function f1, Function f2) { double result = 0.0; Map<ComplexType, Integer> usedTypesFct1 = f1.getTotalComplexTypes(); Map<ComplexType, Integer> usedTypesFct2 = f2.getTotalComplexTypes(); Set<ComplexType> usedTypesTotal = new HashSet<ComplexType>(); Set<ComplexType> usedTypesCommon = new HashSet<ComplexType>(); for (ComplexType t : usedTypesFct1.keySet()) { if (t.equals(PrimitiveType.voidType) == false && t.equals(ComplexType.anonymousType) == false) { usedTypesTotal.add(t); } } for (ComplexType t : usedTypesFct2.keySet()) { if (t.equals(PrimitiveType.voidType) == false && t.equals(ComplexType.anonymousType) == false) { boolean newType = usedTypesTotal.add(t); if (newType == false) { usedTypesCommon.add(t); } } } if (usedTypesTotal.size() > 0) { result = (100.0 * usedTypesCommon.size()) / usedTypesTotal.size(); } return result; }
/** * Méthode appelée pour le calcul de la cohésion entre 2 fonctions. * * <p>Calcule le pourcentage d'appels de fonction communs dans les deux fonctions sur le nombre * total d'appels dans les deux fonctions. Les paramètres des appels ne sont pas pris en compte. * * @param f1 Une fonction d'un modèle de code source * @param f2 Une autre fonction d'un modèle de code source * @return Un double entre 0.0 et 100.0 * @see #cohesion(Function, Function) */ private double cohesionCalls(Function f1, Function f2) { double result = 0.0; Set<Call> calls1 = f1.getTotalCalls(); Set<Call> calls2 = f2.getTotalCalls(); Set<Function> fctCalledTotal = new HashSet<Function>(); Set<Function> fctCalledCommon = new HashSet<Function>(); for (Call call : calls1) { fctCalledTotal.add(call.getFunction()); } for (Call call : calls2) { boolean added = false; added = fctCalledTotal.add(call.getFunction()); if (added == false) { fctCalledCommon.add(call.getFunction()); } } if (fctCalledTotal.size() > 0) { result = (100.0 * fctCalledCommon.size()) / fctCalledTotal.size(); } return result; }
/** * Méthode appelée pour le calcul de la cohésion entre 2 fonctions. * * <p>Calcule le pourcentage de variables locales similaires entre les deux fonctions sur le * nombre total de variables locales utilisées dans les deux fonctions. * * @param f1 Une fonction d'un modèle de code source * @param f2 Une autre fonction d'un modèle de code source * @return Un double entre 0.0 et 100.0 * @see #cohesion(Function, Function) */ private double cohesionLocalVars(Function f1, Function f2) { double result = 0.0; double nbCommon = 0; Map<LocalVariable, Integer> localVars1 = f1.getLocalVariables(); Map<LocalVariable, Integer> localVars2 = f2.getLocalVariables(); for (LocalVariable var1 : localVars1.keySet()) { for (LocalVariable var2 : localVars2.keySet()) { if (var1.getName().length() >= VARNAME_MIN_LEN && var2.getName().length() >= VARNAME_MIN_LEN) { if (var1.getType().equals(var2.getType())) { if (similarity.similar(var1.getName(), var2.getName())) { ++nbCommon; } } } } } double nbPairs = localVars1.size() * localVars2.size(); if (nbPairs > 0) { result = 100.0 * nbCommon / nbPairs; } return result; }
/** * Méthode appelée pour le calcul de la cohésion entre 2 fonctions. * * <p>Calcule le pourcentage de variables globales au programme accédées en commun sur le nombre * total de variables globales au programme accédées dans les deux fonctions. * * @param f1 Une fonction d'un modèle de code source * @param f2 Une autre fonction d'un modèle de code source * @return Un double entre 0.0 et 100.0 * @see #cohesion(Function, Function) */ private double cohesionGlobalVars(Function f1, Function f2) { double result = 0.0; Map<GlobalVariable, Integer> globalVars1 = f1.getCoreGlobalVariables(); Map<GlobalVariable, Integer> globalVars2 = f2.getCoreGlobalVariables(); Set<GlobalVariable> globalVarsTotal = new HashSet<GlobalVariable>(); Set<GlobalVariable> globalVarsCommon = new HashSet<GlobalVariable>(); for (GlobalVariable var : globalVars1.keySet()) { globalVarsTotal.add(var); } for (GlobalVariable var : globalVars2.keySet()) { boolean newVar = globalVarsTotal.add(var); if (newVar == false) { globalVarsCommon.add(var); } } if (globalVarsTotal.size() > 0) { result = (100.0 * globalVarsCommon.size()) / globalVarsTotal.size(); } return result; }
/** * Évalue la cohésion entre une fonction et un type. * * <p>La cohésion entre une fonction <em>f</em> et un type <em>t</em> est égal au pourcentage * d'utilisations de <em>t</em> par <em>f</em> sur le nombre total d'utilisations de l'ensemble * des types utilisés par <em>f</em>. * * @param fct Une fonction d'un modèle de code source * @param type Un type d'un modèle de code source * @return Un double entre 0.0 et 100.0 */ private double cohesion(final Function fct, ComplexType type) { double result = 0.0; double nbUsesOfType = 0.0; double total = 0.0; // Total uses of types Map<ComplexType, Integer> usedTypes = fct.getTotalComplexTypes(); for (ComplexType t : usedTypes.keySet()) { if (t.equals(type)) { nbUsesOfType += usedTypes.get(t); } total += usedTypes.get(t); } // Same file ? if (fct.getSourceFile() != null && type.getSourceFile() != null) { if (fct.getSourceFile().equals(type.getSourceFile())) { nbUsesOfType *= BONUS_SAME_FILE; } } if (total > 0) { result = 100.0 * nbUsesOfType / total; } return result; }
/** * Évalue la cohésion entre une fonction et une variable globale. * * <p>La cohésion entre une fonction f et une variable globale au programme (resp. au fichier) v * est égale au pourcentage d'accès à v sur le nombre total d'accès à des variables globales. * * @param fct Une fonction d'un modèle de code source * @param var Une variable d'un modèle de code source * @return Un double entre 0.0 et 100.0 */ private double cohesion(final Function fct, GlobalVariable var) { double result = 0.0; double total = 0.0; // Total accesses double nbAccessToVar = 0.0; Map<GlobalVariable, Integer> fctVars = fct.getCoreGlobalVariables(); for (Integer n : fctVars.values()) { total += n; } if (fctVars.containsKey(var)) { nbAccessToVar = fctVars.get(var); // Same file ? if (fct.getSourceFile() != null && var.getSourceFile() != null) { if (fct.getSourceFile().equals(var.getSourceFile())) { nbAccessToVar *= BONUS_SAME_FILE; } } } if (total > 0) { result = 100.0 * nbAccessToVar / total; } return result; }
/** * Évalue la cohésion de 2 fonctions. * * <p>La cohésion de 2 fonctions est évaluée sur la moyenne des pourcentages : * * <ul> * <li>de variables globales communes * <li>de variables locales communes * <li>de types communs * <li>d'appels de fonction communs * </ul> * * et sur l'appartenance à un même fichier. * * @param f1 Une fonction d'un modèle de code source * @param f2 Une autre fonction d'un modèle de code source * @return Un double entre 0.0 et 100.0 */ private double cohesion(final Function f1, final Function f2) { double result = 0.0; double cc = this.cohesionCalls(f1, f2); double cg = this.cohesionGlobalVars(f1, f2); double cl = this.cohesionLocalVars(f1, f2); double ct = this.cohesionTypes(f1, f2); double ca = this.cohesionArguments(f1, f2); result += WEIGHT_FCT_COHESION_CALLS * cc; result += WEIGHT_FCT_COHESION_GLOBALS * cg; result += WEIGHT_FCT_COHESION_LOCALS * cl; result += WEIGHT_FCT_COHESION_TYPES * ct; result += WEIGHT_FCT_COHESION_ARGS * ca; if (f1.getSourceFile() != null && f2.getSourceFile() != null) { if (f1.getSourceFile().equals(f2.getSourceFile())) { result *= BONUS_SAME_FILE; } } result /= WEIGHT_FCT_COHESION_CALLS + WEIGHT_FCT_COHESION_GLOBALS + WEIGHT_FCT_COHESION_LOCALS + WEIGHT_FCT_COHESION_TYPES + WEIGHT_FCT_COHESION_ARGS; result = (result > 100.0) ? 100.0 : result; // System.out.println(f1.getName() + " - " + f2.getName() + " : " // + "CC=" + cc + " CG=" + cg + " CL=" + cl + " CT=" + ct // + " CA=" + ca + " -- " + result); // DBG return result; }