
-
Литература
-
Бахтизин В.В., Глухова Л.А. Стандартизация и сертификация программного обеспечения: Учеб. пособие. – Мн.: БГУИР, 2006.
-
Глухова Л.А. Электронный учебно-методический комплекс «Метрология, стандартизация и сертификация в информатике и радиоэлектронике» для студентов специальности I-40 01 01 Программное обеспечение информационных технологий: Учеб. пособие. – Мн.: БГУИР, 2009.
-
Изосимов А.В., Рыжко А.Л. Метрическая оценка качества программ. – М.: МАИ, 1989.
Приложение А. Исходный код главного модуля программы
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Metrics
{
public partial class PLLM : Form
{
string s,filename;
string[] f1 = new string[20];
string[] f2 = new string[30];
string[] f3 = new string[79];
string[] f4 = new string[92];
string[] OpUsedInNativeFuncs = new string[1000];
string[] blocks = new string[6] { "program", "uses", "const", "var", "type", "label"};
string[] DT = new string[17] { "shortint","integer","longint","byte","word","real","single","double","extended","comp","char","boolean","string","array","record","set","of" };
string[] ReservedWords = new string[8] {"until","array","begin","do","downto","then","end","to" };
char[] Arithm = new char[4] { '-', '/', '+', '*'};
string[] LoadedCode = new string[1000];
string[] dictOperator = new string[10000]; //unique operators
string[] dictOperand = new string[10000]; //unique operands
int[] numOperator = new int[10000]; //number of operators
int[] numOperand = new int[10000];//number of operands
double[] DBCoefficients = new double[500];
//int[,] blocks = new int[7, 2];//Blocks entrance and quit (0-program,1-uses,2-label,3-type,4-const,5-var,6-begin..end.)
int codelen,curpos,posnat=0;
int eta1 = 0, eta2 = 0, n1 = 0, n2 = 0, etaR = 0;
int numstr,begin_end=0;
double V, Lambda, Vr,CurPLL;
bool comment=false,literal=false,param=false,uses_program=false,procedure_function=false;
FileInfo SrcFile,DBFile;
StreamReader /*fdes,*/DBStream;
public PLLM()
{
InitializeComponent();
}
private void CleanData()
{
int i;
for (i = 0; i <= 999; i++)
{
numOperand[i] = 0;
OpUsedInNativeFuncs[i] = "";
numOperator[i] = 0;
dictOperand[i] = "";
dictOperator[i] = "";
}
}
private string[] LoadExisting(string pathname,int len)
{
//crt 20,dos 33, graph 79,system 92
string tmps;
string[] u = new string[100];
FileInfo URF;
StreamReader URF_1;
int i;
URF = new FileInfo(pathname);
URF_1 = URF.OpenText();
for (i = 0; i <= len-1; i++)
{
tmps = URF_1.ReadLine();
tmps = tmps.ToLower();
u[i] = tmps;
}
URF_1.Close();
return (string[])u.Clone();
}
private void ParseString(string str)
{
int i, j,pos=0;
bool IDFound, exists;
string ts="";
char tc=' ',prev=' ';
char[] codestr=new char[128];
char[] newID = new char[100];
codestr=str.ToCharArray();
IDFound = false;
for (i = 0; i <= str.Length; i++)
{
prev = tc;
if (i==str.Length) tc=' ';
else
tc = codestr[i];
if (Convert.ToInt32(tc) == 39)
literal = !(literal);
if (Convert.ToInt32(prev) == 123) comment = true;
if (Convert.ToInt32(prev) == 125) comment = false;
if ((!literal) && (!comment))
{
if (Char.IsLetterOrDigit(tc))
{
if ((!(Char.IsLetter(prev))) && (!(Char.IsNumber(prev))) && (Char.IsLetter(tc)))
{
if (Convert.ToInt16(prev) != 39)
IDFound = true;
for (j = 0; j <= 99; j++)
newID[j] = ' ';
pos = 0;
newID[pos] = tc;
}
else
{
pos++;
newID[pos] = tc;
}
}
else
{
if ((Char.IsLetterOrDigit(prev)) && IDFound)
{
IDFound = false;
ts = new string(newID);
ts = ts.Trim();
exists = false;
for (j = 0; j <= curpos - 1; j++)
if (ts == dictOperand[j])
{
exists = true;
numOperand[j]++;
}
if (((!exists)&&(!uses_program))||(procedure_function))
{
dictOperand[curpos] = ts;
numOperand[curpos] = 1;
curpos++;
}
if ((ts == "uses") || (ts == "program"))
uses_program = true;
if ((ts == "procedure") || (ts == "function"))
{
procedure_function = true;
begin_end = 0;
}
if ((ts=="begin")||(ts == "case"))
begin_end++;
if (ts == "end")
{
begin_end--;
if (begin_end==0)
procedure_function = false;
}
if (param)
{
bool q = false;
for (int l = 0; l <= posnat-1; l++)
if (OpUsedInNativeFuncs[l] == ts)
q = true;
if (!q)
{
etaR++;
posnat++;
OpUsedInNativeFuncs[posnat - 1] = ts;
}
}
}
switch (tc)
{
case ';':
{
numOperator[0]++;
if (uses_program)
uses_program = false;
}
break;
case '-':
numOperator[3]++;
break;
case '+':
numOperator[4]++;
break;
case '*':
numOperator[5]++;
break;
case '/':
numOperator[6]++;
break;
case '=':
{
if (prev == ':')
numOperator[1]++;
else
numOperator[2]++;
break;
}
case '\'':
numOperator[7]++;
break;
case ',':
numOperator[8]++;
break;
case '(':
numOperator[9]++;
if (NativeChk(ts))
param = true;
break;
case ')':
param = false;
break;
default:
break;
}
}
}
}
}
private void openSourceCodeToolStripMenuItem_Click(object sender, EventArgs e)
{
openSourceCode();
}
private void openSourceCode()
{
int i;
CleanData();
for (i = 0; i <= 999; i++)
LoadedCode[i] = "";
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
richTextBox1.LoadFile(openFileDialog1.FileName, RichTextBoxStreamType.PlainText);
SrcFile = new FileInfo(openFileDialog1.FileName);
analyzeToolStripMenuItem.Enabled = true;
closeSourceCodeToolStripMenuItem.Enabled = true;
saveToolStripButton.Enabled = true;
toolStripButton1.Enabled = true;
copyToolStripButton.Enabled = true;
toolStripButton2.Enabled = true;
//fdes = SrcFile.OpenText();
/*
codelen = 0;
s = fdes.ReadLine();
while (s != null)
{
s = s.ToLower();
s = s.Trim();
LoadedCode[codelen] = s;
s = fdes.ReadLine();
codelen++;
}
codelen--;*/
}
this.Text = "Programming Language Level Metrics" + " - [" + openFileDialog1.FileName + "]";
}
private void LoadSC()
{
codelen = 0;
s = richTextBox1.Lines[codelen];
while (codelen<=richTextBox1.Lines.Length-1)
{
s = s.ToLower();
s = s.Trim();
LoadedCode[codelen] = s;
s = richTextBox1.Lines[codelen];
codelen++;
}
codelen--;
}
private void Analyze()
{
int i,j,cpos;
eta1 = 0; eta2 = 0; n1 = 0; n2 = 0; etaR = 0;
bool endIdent = false, isRes = false;
//char[] liq = new char[7] { ' ', ';', '.', ':', '!', '?', '\n' };
CleanData();
LoadSC();
curpos = 0;
comment = false; literal = false; param = false; uses_program = false; procedure_function = false;
dictOperator[0] = ";";
dictOperator[1] = ":=";
dictOperator[2] = "=";
dictOperator[3] = "-";
dictOperator[4] = "+";
dictOperator[5] = "*";
dictOperator[6] = "/";
dictOperator[7] = "'";
dictOperator[8] = ",";
dictOperator[9] = "(";
for (i = 0; i <= codelen; i++)
{
ParseString(LoadedCode[i]);
}
for (i = 0; i <= curpos; i++)
{
isRes = false;
for (j = 0; j <= 5; j++)
if (dictOperand[i] == blocks[j])
isRes = true;
for (j = 0; j <= 16; j++)
if (dictOperand[i] == DT[j])
isRes = true;
for (j = 0; j <= 7; j++)
if (dictOperand[i] == ReservedWords[j])
isRes = true;
if (isRes)
numOperand[i] = 0;
}
cpos = 10;
for (i = 0; i <= curpos - 1; i++)
{
//MessageBox.Show(dictOperand[i]+';'+Convert.ToString(numOperand[i]));
if (dictOperand[i] == "begin")
{
endIdent = true;
}
if (endIdent)
{
dictOperator[cpos] = dictOperand[i];
numOperator[cpos] = numOperand[i];
numOperand[i] = 0;
dictOperand[i] = "";
cpos++;
}
}
numOperator[0]--;
for (i = 0; i <= curpos - 1; i++)
if ((!String.IsNullOrEmpty(dictOperand[i]))&&(numOperand[i]!=0))
{
eta2++;
n2+=numOperand[i];
}
for (i = 0; i <= cpos - 1; i++)
if ((!String.IsNullOrEmpty(dictOperator[i])) && (numOperator[i] != 0))
{
eta1++;
n1 += numOperator[i];
}
eta2 += numOperator[7];
n2 += numOperator[7];
Vr = VNCalculate();
V = (n1+n2) * Math.Log((eta1 + eta2), 2);
//Lambda = L * L * V;
Lambda = Vr * Vr / V;
MessageBox.Show("PLL equals "+Convert.ToString(Lambda));
}
private double VNCalculate()
{
int etatmp = 0,i,j;
for (j = 0;j<=999;j++)
{
for (i = 0; i <= 19; i++)
if (dictOperator[j] == f1[i])
etatmp++;
for (i = 0; i <= 32; i++)
if (dictOperator[j] == f2[i])
etatmp++;
for (i = 0; i <= 78; i++)
if (dictOperator[j] == f3[i])
etatmp++;
for (i = 0; i <= 91; i++)
if (dictOperator[j] == f4[i])
etatmp++;
}
return etatmp * (Math.Log(etatmp, 2));
}
private bool NativeChk(string s)
{
int i;
bool c = false;
for (i = 0; i <= 19; i++)
if (s == f1[i])
c = true;
for (i = 0; i <= 32; i++)
if (s == f2[i])
c = true;
for (i = 0; i <= 78; i++)
if (s == f3[i])
c = true;
for (i = 0; i <= 91; i++)
if (s == f4[i])
c = true;
return c;
}
private void CloseSC()
{
CleanData();
richTextBox1.Clear();
closeSourceCodeToolStripMenuItem.Enabled = false;
analyzeToolStripMenuItem.Enabled = false;
saveToolStripButton.Enabled = false;
toolStripButton1.Enabled = false;
copyToolStripButton.Enabled = false;
toolStripButton2.Enabled = false;
this.Text = "Programming Language Level Metrics";
}
private void closeSourceCodeToolStripMenuItem_Click(object sender, EventArgs e)
{
CloseSC();
}
private void OpenDB()
{
string s1;
int pos;
if (openFileDialog2.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
DBFile = new FileInfo(openFileDialog2.FileName);
filename = openFileDialog2.FileName;
closeDatabaseToolStripMenuItem.Enabled = true;
pasteToolStripButton.Enabled = true;
toolStripButton3.Enabled = true;
DBStream = DBFile.OpenText();
s1 = DBStream.ReadLine();
numstr = Convert.ToInt16(s1.Substring(11, s1.Length - 11));
s1 = DBStream.ReadLine();
CurPLL = Convert.ToDouble(s1.Substring(4, s1.Length - 4));
MessageBox.Show("Уровень языка программирования равен " + Convert.ToString(CurPLL));
s1 = DBStream.ReadLine();
pos = 0;
while (s1 != null)
{
DBCoefficients[pos] = Convert.ToDouble(s1);
s1 = DBStream.ReadLine();
pos++;
}
DBStream.Close();
addToDatabaseToolStripMenuItem.Enabled = true;
}
this.Text = "Programming Language Level Metrics" + " - [" + openFileDialog1.FileName + "], Database: [" + openFileDialog2.FileName + "]";
}
private void openResultDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenDB();
}
private void AddToDB()
{
double avg;
StreamWriter SW = File.CreateText(filename);
DBCoefficients[numstr] = Lambda;
numstr++;
SW.WriteLine("totallines=" + Convert.ToString(numstr));
avg = 0;
for (int i = 0; i <= numstr - 1; i++)
avg += DBCoefficients[i];
avg /= numstr;
SW.WriteLine("PLL=" + Convert.ToString(avg));
for (int i = 0; i <= numstr - 1; i++)
{
SW.WriteLine(Convert.ToString(DBCoefficients[i]));
}
SW.Close();
MessageBox.Show("Средний уровень языка программирования равен " + Convert.ToString(avg));
}
private void addToDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
{
AddToDB();
}
private void CreateDB()
{
if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
DBFile = new FileInfo(saveFileDialog1.FileName);
filename = saveFileDialog1.FileName;
closeDatabaseToolStripMenuItem.Enabled = true;
addToDatabaseToolStripMenuItem.Enabled = true;
toolStripButton3.Enabled = true;
pasteToolStripButton.Enabled = true;
this.Text = "Programming Language Level Metrics" + " - [" + openFileDialog1.FileName + "], Database: [" + openFileDialog2.FileName + "]";
}
}
private void createDatabase_Click(object sender, EventArgs e)
{
CreateDB();
}
private void closeDatabaseToolStripMenuItem_Click(object sender, EventArgs e)
{
addToDatabaseToolStripMenuItem.Enabled = false;
closeDatabaseToolStripMenuItem.Enabled = false;
toolStripButton3.Enabled =false;
pasteToolStripButton.Enabled = false;
this.Text = "Programming Language Level Metrics" + " - [" + openFileDialog1.FileName + "]";
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
About aboutDialog = new About();
aboutDialog.ShowDialog();
}
private void metricsHelpToolStripMenuItem_Click(object sender, EventArgs e)
{
Help helpDialog = new Help();
helpDialog.ShowDialog();
}
private void analyzeToolStripMenuItem_Click(object sender, EventArgs e)
{
Analyze();
}
private void toolStripButton1_Click_1(object sender, EventArgs e)
{
Analyze();
}
private void openToolStripButton_Click(object sender, EventArgs e)
{
openSourceCode();
}
private void saveToolStripButton_Click(object sender, EventArgs e)
{
CloseSC();
}
private void copyToolStripButton_Click(object sender, EventArgs e)
{
CreateDB();
}
private void toolStripButton2_Click(object sender, EventArgs e)
{
OpenDB();
}
private void toolStripButton3_Click(object sender, EventArgs e)
{
AddToDB();
}
private void pasteToolStripButton_Click(object sender, EventArgs e)
{
addToDatabaseToolStripMenuItem.Enabled = false;
closeDatabaseToolStripMenuItem.Enabled = false;
toolStripButton3.Enabled = false;
pasteToolStripButton.Enabled = false;
this.Text = "Programming Language Level Metrics" + " - [" + openFileDialog1.FileName + "]";
}
private void helpToolStripButton_Click(object sender, EventArgs e)
{
Help helpDialog = new Help();
helpDialog.ShowDialog();
}
private void PLLM_Load(object sender, EventArgs e)
{
if (File.Exists("crt.urf"))
{
f1 = LoadExisting("crt.urf", 20);
f2 = LoadExisting("dos.urf", 33);
f3 = LoadExisting("graph.urf", 79);
f4 = LoadExisting("system.urf", 92);
}
else
{
MessageBox.Show("Нет файлов.");
this.Close();
}
}
private void formulasToolStripMenuItem_Click(object sender, EventArgs e)
{
Formula frm = new Formula();
frm.ShowDialog();
}
}
}
Приложение Б. Пример кода, проанализированного данным ПС.
program bacteries01;
var
i,g,r,n,k:longint;
begin
Writeln('Insert the quantity of red bacteries');
Readln(n);
Writeln('Insert the number of time tacts');
Readln(k);
r:=n;
g:=0;
i:=1;
repeat
g:=g+r;
r:=g-r;
i:=i+1;
until i>k;
Writeln(k,' tacts; ',g,' green bacteries; ',r,' red bacteries.');
end.
{
операнды
i 5
g 6
r 6
n 3
k 4
literal 5
всего 10 операндов, сумма 29
операторы
; 14
:= 6
- 1
+ 2
' ' 5
, 9
() 5
writeln 3
readln 2
repeat..until 1
всего 10 операторов, сумма 48
n*=11 (2 имплиментарных функции - readln, writeln с 9 параметрами - n,k,g,r+5 литералов)
v*=11log(2)11 = 38.054
v=(29+48)log(2)(10+10)=77log(2)20 = 332.788
PLL = (v*)^2/v=4.351
}
Приложение В. Пример базы данных статистики вычислений уровня языка программирования.
totallines=22
PLL=2,16937514598311
3,04556502192603
1,46357964910235
1,49592272289484
1,150768440858
2,91497902406523
1,150768440858
0,428559002805344
0,4038946805358
0,0199243335732832
0,131666098623164
2,73952167239007
1,29801455576374
0,0384208203878047
2,69763038935442
1,07754872480515
0,294577574811578
0,409763417168128
0,431201000129267
17,270122715265
5,52175535835755
0,347407172168881
3,39466239578476