4.9 KiB
Complexité Cyclomatique
Calcul de la complexité cyclomatique pour chaque fonctions
Pour chaque fonction, un diagramme est proposé dans ping-report/diagrammes/nom de la fonction approprié.
-- Dans daemon.c
- create_daemon() : 4
- ping_request() : 2
- send_check() : 2
- check_keep_working() : 4
- daemon_work() : 3
- ping-report main() : 5
- write_pid_file() : 2
- get_ping_from_temp_log : 12
- write_ping_log : 3
- set_stats_ping() : 10
Toute fonction non mentionnée dans la liste a une complexité cyclomatique de 1, et donc ne nécessite pas un diagramme.
Dans un second temps, on va amélorier la complexité cyclomatique des fonctions les plus lourdes si possible. On va commencer par get_ping_from_temp_log. La méthode la plus efficace pour réduire la compléxité cyclomatique d'un programme, outre changer la nature du code, est de factoriser la fonction, c'est à dire d'écrire un segment du code coûteux dans une fonction à part puis de l'appeler.
On a décidé de faire cela pour la boucle while de la fonction. Cela nous donne le code suivant :
void while_from_gpftl(char* read_line, size_t* n, FILE* fd, regex_t* p_reg, regmatch_t* pmatch, size_t* nmatch, int* start, int* end, size_t* size_ping, char* ping){
while(getline(&read_line,n,fd) != -1){
if(read_line == NULL){
break;
}
/* Exec regex to find ping */
if(regexec(p_reg,read_line,*nmatch,pmatch,0) == 0){
/* Extract ping position from read line */
*start = (int) pmatch[1].rm_so;
*end = (int) pmatch[1].rm_eo;
*size_ping = (size_t) ((*end) - (*start));
/* ping string memory allocation */
ping = malloc(sizeof(char) * ((*size_ping)+2));
if(ping == NULL){
free(read_line);
read_line = NULL;
*n = 0;
break;
}
/* Create ping string */
(void) strncpy(ping, &read_line[*start], *size_ping);
ping[*size_ping]='\n';
ping[*size_ping+1]='\0';
/* Free memory */
free(read_line);
read_line = NULL;
*n = 0;
break;
}
}
char* better_get_ping_from_temp_log(){
/* Variables */
FILE* fd = NULL;
char* read_line = NULL;
size_t n = 0;
size_t nmatch = 2;
regex_t* p_reg;
regmatch_t* pmatch;
char* ping = NULL;
int start;
int end;
size_t size_ping;
/* regex struct memory allocation */
p_reg = (regex_t *) malloc(sizeof(*p_reg));
if(p_reg == NULL){
return ping; /* NULL */
}
/* Open ping log file */
fd = fopen("/var/log/ping-report/last-ping.log","r");
if(fd == NULL){
free(p_reg);
return ping; /* NULL */
}
/* Construct regex to get ping from log file */
if(regcomp(p_reg,"time=(.*) ms",REG_EXTENDED) != 0){
if(p_reg != NULL){
free(p_reg);
}
(void) fclose(fd);
return ping; /* NULL */
}
/* match info memory allocation */
pmatch = malloc(sizeof(*pmatch) * nmatch);
if(pmatch == NULL){
(void) fclose(fd);
regfree(p_reg);
free(p_reg);
return ping; /* NULL */
}
while_from_gpftl(read_line, &n, fd, p_reg, pmatch, &nmatch, &start, &end, &size_ping, ping);
/* free allocated memory */
regfree(p_reg);
free(p_reg);
free(pmatch);
if(read_line != NULL){
free(read_line);
}
(void) fclose(fd);
/* ping may be null, then it must mean that the ping request was lost */
return ping;
}
Vous pouvez retrouver le diagramme dans le répertoire ping-report/diagrammes/better_get_ping_from_temp_log.mdj. La complexité cyclomatique de l'algorithme sous cette forme est de 7.
On peut appliquer le même principe à set_stats_ping en factorisant le segment suivant de la fonction :
void trop_de_ifs(char* read_line, int* nb_loss, double* ping, int* nb_ping, double* max, double* min, int* nb_high, double* sum){
if(strcmp(read_line,"LOSS") == 0){
(*nb_loss)++;
}else{
/* Evaluate the ping as a double */
*ping = strtod(read_line,NULL);
/* Test null ping */
if(*ping < 0.1){
/* Ignore null ping */
}else{
/* Number of ping readed (for mean calculation) */
*nb_ping++;
/* Max ping */
if(*ping > *max){
*max = *ping;
}
/* Min ping */
if(*ping < *min){
*min = *ping;
}
/* Number of ping above 100 ms */
if(*ping > 100.0){
*nb_high++;
}
/* Sum (for mean calculation) */
sum += *ping;
}
}
}
Vous pouvez retrouver le diagramme dans le répertoire ping-report/diagrammes/better_set_stats_ping. La complexité cyclomatique de l'algorithme sous cette forme est de 4.