מטריקת תוכנה

מטריקת תוכנה (גם מדיד תוכנה, באנגלית Software metric) היא שיטה למדידת תכונות מסוימות של חלקי תוכנה או הדרישות שלה. המטרה היא לאבחן כמה הקוד או המבנה מסובך, ומה הסיכוי להמצאות באגים בתוכנה.
קיים מגוון סוגים של שפות תכנות כגון: שפות פרוצדרוליות, שפות מונחות עצמים ועוד, בגלל השוני ביניהן יהיו מספר סוגים של מטריקות.

סיבוכיות מעגלית (Cyclomatic complexity)

סיבוכיות מעגלית של קטע קוד היא מספר המסלולים הבלתי תלויים בגרף של קטע הקוד.
לדוגמה, עבור קטע קוד שלא מכיל צומתי החלטה כגון תנאים או לולאות, הסיבוכיות היא בדיוק 1 משום שקיים מסלול יחיד בקוד.
אם קטע קוד מכיל תנאי יחיד, ישנם 2 מסלולים שונים בקוד משום שכל תנאי יכול להיות אמת או שקר ולכן הסיבוכיות במקרה הזה תהיה 2.
באופן מתמטי, סיבוכיות מעגלית של תוכנית מוגדרת בעזרת גרף הזרימה של התוכנית שמוגדר להיות גרף מכוון שמכיל את הבלוקים הבסיסיים של התוכנית, כאשר ישנה קשת מקודקוד אחד לאחר אם קיים תרחיש שעבורו לאחר ביצוע השורה המייצגת את הקודקוד הראשון נבצע את השורה המייצגת את הקודקוד השני. הסיבוכיות M מוגדרת להיות:
M = E-V+2P כאשר, 
E - מספר הקשתות בגרף.
V - מספר הקודקודים (בלוקים) בגרף.
P - מספר רכיבי הקשירות בגרף.

דוגמה

בקוד שלפנינו מספר הקשתות בגרף 11, מספר הקודקודים 10, וישנו רכיב קשירות בודד ולכן נקבל כי M=11-10+1*2 = 3
for (int i=0 ; i< N ; i++)
 cout<< i <<endl;for (int i=0; i<N ; i++)
 cout<<i*i<<endl;

מספר שורות קוד (LOC)

מספר שורות קוד (LOC) היא מטריקה למדידת גודל של תכנה על ידי ספירת מספר שורות הקוד בקוד המקור של התוכנית. מטריקה זו יכולה לתת לנו הערכה טובה למאמץ הנדרש לפיתוח התכנה ולתחזוקתה. במטריקה זו מודדים את מספר השורות הפיזיות ולא הלוגיות, אף שיש חיסרון בהסתכלות על מספר השורות הפיזיות ולא הלוגיות.
לדוגמה, נסתכל על קטע הקוד הבא בשפת C:
for (i = 0; i < 100; i++) printf("hello");
בקוד זה יש שורה פיזית אחת ושתי שורות לוגיות.
לעומת זאת, מתכנת אחר יכול לרשום את אותו הקוד בצורה הזאת:
for (i = 0; i < 100; i++){
 printf("hello");}
בקוד הנ"ל יש 4 שורות קוד פיזיות ושתי שורות לוגיות.
כלומר, מספר שורות הקוד הפיזיות תלוי מאוד במתכנת אך הוא עדיין יכול לתת לנו אינדיקציה טובה על סדר הגודל של התוכנה.

קשרים בין מחלקות (CBO)

במטריקה זו אנו מודדים את הצימוד (Coupling) בין אובייקטים.
CBO עבור מחלקה מסוימת מוגדר להיות המספר הכולל של ההפניות מהמחלקה למחלקות אחרות וההפניות מהמחלקות האחרות למחלקה.
ככל שהצימוד גבוה יותר, כך המערכת מועדת יותר לבאגים.
דוגמה

קשרים בין שיטות (RFC)

Response set For Class עבור מחלקה, מוגדר להיות מספר המתודות בקבוצת כל המתודות שיכולות לפעול כתוצאה ממסר שנשלח לאובייקט המחלקה.
דוגמה בשפת Java:
Class 2DPoint{
 private int x;
 private int y;
 public 2DPoint(int x,int y){
 this.x = x;
 this.y = y;
 }
 public distance(int x1,int y1){
 return Math.sqrt(Math.pow((x-x1),2) + Math.pow((y-y1),2));
 }
 public distanceFromOrigin(){
 return this.distance(0,0);
 }}
המחלקה 2DPoint מייצגת נקודה בדו-מימד.
השיטה שיכולה להיות מופעלת כתוצאה משליחת מסר לאובייקט של המחלקה הנ"ל היא distance.
כלומר, ה-RFC של מחלקה זו הוא 1.

ככל שערך ה-RFC גדול יותר כך המחלקה, לפי מדד זה, נחשבת למסובכת יותר ומועדת יותר לבאגים.

Cohesion metrics

מטריקת הלכידות באה למדוד כמה שיטות של המחלקה קשורות זו לזו, נראה שתי שיטות כאלו:

חוסר קשר בין שיטות (LCOM)

אנו רוצים למדוד את חוסר הקשר בין השיטות על ידי התבוננות בכמה משתנים מהמחלקה כל שיטה משתמשת.
נניח שיש לנו מ שיטות במחלקה ויש סה"כ k משתנים במחלקה אז עבור כל שיטה נחשב את ה-LCOM שלה כך:

נסתכל על כל זוגות המשתנים אצלנו, נגדיר את P להיות מספר הזוגות (Ii, Ij), שהשיטה m משתמשת גם ב-Ii וגם ב-Ij, ונגדיר את Q להיות את כל השאר הזוגות, אז (|LCOM(m) = max(0, |P|-|Q.
לקבלת ה-LCOM עבור המחלקה נסכום את כל ה-LCOM עבור כל השיטות שלה.

קשר בין שיטות (TCC)

מה שאנו רוצים לבדוק בשיטה זו זה כמה שיטות משתמשות באותן המשתנים (כלומר יש ביניהם קשר כלשהו).

נגדיר NP להיות המספר המקסימלי של קשרים בין שיטות (כלומר מספר הזוגות של השיטות במחלקה).

נגדיר NDC להיות מספר הקשרים הישירים כלומר בכמה זוגות של שיטות יש שימוש באותו משתנה.

ונקבל כי TCC=NDC/NP, כלומר היחס בין הקשרים הישירים לבין מספר הקשרים שאפשרי.
כאשר ככל שה-TCC קטן יותר ככה המחלקה פחות מורכבת.

ככלל אנו מבדילים בין מחלקות עם TCC שקטן מ-0.5 לבין מחלקות עם TCC שגדול מ-0.5.

מטריקות הורשה (Inheritance related measures)

עד עתה לא התחשבנו בירושה, כאשר בשפות תכנות מונחות עצמים ההורשה היא חלק מרכזי, נשים לב שעד עתה הסתכלנו על מספר המשתנים/שיטות במחלקה, אך לא דיברנו על הורשה, מכיוון שאם מחלקה A יורשת ממחלקה B אז לא נראה את השיטות של מחלקה B בתוך A ועל מנת להעריך את A אנו חייבים להתייחס גם למחלקה B.

עומק עץ ההורשה (DIT)

נגדיר עבור כל מחלקה את עומק עץ ההורשה שלה, כאשר ככל שהעומק גדול יותר ככה הסיכוי לבאגים גדל, הסיבה היא שככל שאנו יורדים בעץ ההורשה אנו מקבלים עוד שיטות ומשתנים מה"הורים" שלנו ולכן "מסבכים" את המחלקה.

סטטיסטית קרוב ל-83% מהמחלקות הן בעומק 0 או 1 וכל השאר בעומקים הגדולים מ-1 כפי שרואים בתרשים.

מספר ילדים למחלקה (NOC)

בשיטה הקודמת חיפשנו מה העומק של המחלקה, עתה נרצה דווקא לראות מה רוחב ההורשה של המחלקה, כלומר כמה בנים ישירים יש לה (בנים של בנים לא נכנסים בחישוב), הסיבה היא שבעומק יש לנו הרבה יותר שימוש מחדש בקוד ואילו ברוחב יש פחות כי כל מחלקה מממשת את השיטות שלה בצורה שונה.
כמו כן, מחקרים הראו כי NOC גבוה גורם לפחות שגיאות.