מטריקת תוכנה

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

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

==מטריקות בתכנות פרוצדורלי==
===סיבוכיות מעגלית (Cyclomatic complexity)===

סיבוכיות מעגלית של קטע קוד היא מספר המסלולים הבלתי תלויים בגרף של קטע הקוד.

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

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

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

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

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

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

לדוגמה, נסתכל על קטע הקוד הבא בשפת C:

<syntaxhighlight lang="c">
for (i = 0; i < 100; i++) printf("hello");
</syntaxhighlight>

בקוד זה יש שורה פיזית אחת ושתי שורות לוגיות.

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

<syntaxhighlight lang="c">
for (i = 0; i < 100; i++)
{
 printf("hello");
}
</syntaxhighlight>

בקוד הנ"ל יש 4 שורות קוד פיזיות ושתי שורות לוגיות.

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

===סיבוכיות מערכתית (System complexity)===

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

סיבוכיות מערכתית מורכבת משני חלקים עיקריים:
* סיבוכיות מיבנית (SC) - כמה קריאות יש לפרוצדורות אחרות בתוך הפרוצדורה ולפי זה להעריך את מידת הסיבוכיות המבנית.
: SC יהיה שווה למספר הקריאות לפרוצדורות אחרות בתוך הפרוצדורה בריבוע.
* סיבוכיות המידע (DS)- התחשבות במספר הקלטים/פלטים שיש לפרוצדורה.
: DS מוגדר להיות היחס בין מספר הקלטים/פלטים של פרוצדורה, לבין מספר הקריאות לפרוצדורות אחרות בתוך הפרוצדורה ועוד 1.

הסיבוכיות המערכתית (SYSC) של אוסף פרוצדורות מוגדר להיות סכום ה-DC וה-CS של כל הפרוצדורות

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

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

דוגמה

==== קשרים בין שיטות (RFC) ====
Response set For Class עבור מחלקה, מוגדר להיות מספר המתודות בקבוצת כל המתודות שיכולות לפעול כתוצאה ממסר שנשלח לאובייקט המחלקה.

דוגמה בשפת Java:

<syntaxhighlight lang="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);
 }
}
</syntaxhighlight>

המחלקה 2DPoint מייצגת נקודה בדו-מימד.
השיטה שיכולה להיות מופעלת כתוצאה משליחת מסר לאובייקט של המחלקה הנ"ל היא distance.
כלומר, ה-RFC של מחלקה זו הוא 1.<br />
ככל שערך ה-RFC גדול יותר כך המחלקה, לפי מדד זה, נחשבת למסובכת יותר ומועדת יותר לבאגים.

=== Cohesion metrics ===
מטריקת הלכידות באה למדוד כמה שיטות של המחלקה קשורות זו לזו, נראה שתי שיטות כאלו:
==== חוסר קשר בין שיטות (LCOM) ====
אנו רוצים למדוד את חוסר הקשר בין השיטות על ידי התבוננות בכמה משתנים מהמחלקה כל שיטה משתמשת.
נניח שיש לנו מ שיטות במחלקה ויש סה"כ k משתנים במחלקה אז עבור כל שיטה נחשב את ה-LCOM שלה כך:<br />
נסתכל על כל זוגות המשתנים אצלנו, נגדיר את P להיות מספר הזוגות (Ii, Ij), שהשיטה m משתמשת גם ב-Ii וגם ב-Ij, ונגדיר את Q להיות את כל השאר הזוגות, אז (|LCOM(m) = max(0, |P|-|Q.
לקבלת ה-LCOM עבור המחלקה נסכום את כל ה-LCOM עבור כל השיטות שלה.

==== קשר בין שיטות (TCC) ====
מה שאנו רוצים לבדוק בשיטה זו זה כמה שיטות משתמשות באותן המשתנים (כלומר יש ביניהם קשר כלשהו).<br />
נגדיר NP להיות המספר המקסימלי של קשרים בין שיטות (כלומר מספר הזוגות של השיטות במחלקה).<br />
נגדיר NDC להיות מספר הקשרים הישירים כלומר בכמה זוגות של שיטות יש שימוש באותו משתנה.<br />
ונקבל כי TCC=NDC/NP, כלומר היחס בין הקשרים הישירים לבין מספר הקשרים שאפשרי.
כאשר ככל שה-TCC קטן יותר ככה המחלקה פחות מורכבת.<br />
ככלל אנו מבדילים בין מחלקות עם TCC שקטן מ-0.5 לבין מחלקות עם TCC שגדול מ-0.5.

=== מטריקות הורשה (Inheritance related measures) ===
עד עתה לא התחשבנו בירושה, כאשר בשפות תכנות מונחות עצמים ההורשה היא חלק מרכזי, נשים לב שעד עתה הסתכלנו על מספר המשתנים/שיטות במחלקה, אך לא דיברנו על הורשה, מכיוון שאם מחלקה A יורשת ממחלקה B אז לא נראה את השיטות של מחלקה B בתוך A ועל מנת להעריך את A אנו חייבים להתייחס גם למחלקה B.
==== עומק עץ ההורשה (DIT) ====
נגדיר עבור כל מחלקה את עומק עץ ההורשה שלה, כאשר ככל שהעומק גדול יותר ככה הסיכוי לבאגים גדל, הסיבה היא שככל שאנו יורדים בעץ ההורשה אנו מקבלים עוד שיטות ומשתנים מה"הורים" שלנו ולכן "מסבכים" את המחלקה.<br />
סטטיסטית קרוב ל-83% מהמחלקות הן בעומק 0 או 1 וכל השאר בעומקים הגדולים מ-1 כפי שרואים בתרשים.
עומק עץ ממוצע

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

== קישורים חיצוניים ==
*[https://web.archive.org/web/20160303180053/http://flosshub.org/system/files/Gyimothy.pdf Empirical Validation of Object-Oriented Metrics on Open Source Software for Fault Prediction]
*[http://ijcem.org/papers12011/12011_14.pdf מחקר על מטריקות בתכנות מאתר ijcem]
*[http://www.imagix.com/links/software-metrics.html Software Quality Metrics]
*[http://agile.csc.ncsu.edu/SEMaterials/tutorials/metrics/ Software Metrics tool]

קטגוריה:בדיקות תוכנה
קטגוריה:הנדסת תוכנה