Практическая работа

Практическая работа Разработка программ оценки сложности программного обеспечения

Работа добавлена на сайт bukvasha.net: 2015-10-29

Поможем написать учебную работу

Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 9.11.2024





1 ТЕОРИТИЧЕСКИЕ СВЕДЕНИЯ
Метрики третьей группы базируются на оценке использования, конфигурации и размещения данных в программе. В первую очередь это касается глобальных переменных.

Предполагается методика, связывающая сложность программ с обращениями к глобальным переменным.

Пара “модуль—глобальная переменная” обозначается как (p,
r
), где p—модуль, имеющий доступ к глобальной переменной r. В зависимости от наличия в программе реального обращения к переменной
r
формируются два типа пар “модуль—глобальная переменная”: фактические и возможные.

Возможное обращение к r с помощью p показывает, что область существования r включает в себя p.

Характеристика  говорит о том, сколько раз модули   действительно получали доступ к глобальным переменным, а число  — сколько раз они могли бы получать доступ.

Отношение числа фактических обращений к возможным определяется

                                        .                                                    (7)

Эта формула показывает приближенную вероятность ссылки произвольного модуля на произвольную глобальную переменную.

Очевидно, чем  выше эта вероятность, тем выше вероятность “несанкционированного” изменения какой-либо переменной, что может существенно осложнить работа, связанные с модификацией программы.

Покажем расчет метрики “модуль - глобальная переменная “. Пусть в программе имеются три глобальные переменные и три подпрограммы. Если предположить, что каждая подпрограмма имеет доступ к каждой из переменных, то мы получим девять возможных пар, т. е. = 9. Далее пусть первая программа обращается к одной переменной, вторая — к двум, а третья — не обращается ни к одной переменной. Тогда ,  .

Следующие две метрики сложности потока данных программ зарекомендовали себя с лучшей стороны. Речь идет о спене и метрике Чепина.

Определение спена основывается на локализации обращений к данным внутри каждой программной секции. Спен — это число утверждений, содержащих данный идентификатор, появившийся n раз имеет спен, равный .

Что дает эта метрика? Предположим, мы обнаружили в программе идентификатор, спен которого равен 100. Тогда при построении трассы программы по этому идентификатору, по крайней мере, 100 контролирующих утверждений, что усложняет тестирование и отладку.Следующей метрикой сложности потока данных программ является метрика Чепина. Существуют несколько её модификаций. Рассмотрим наиболее простой, а с точки зрения практического использования — достаточно эффективный вариант этой метрики.

Суть метода состоит в оценке информационной прочности отдельно взятого программного модуля с помощью анализа характера использования переменных из списка ввода-вывода.

Всё множество переменных, составляющих список ввода-вывода, разбивается на четыре функциональные группы:

1.      Р — водимые переменные для расчетов и для обеспечения вывода. Примером может служить используемая в программах лексического анализатора переменная, содержащая строку исходного текста программы, т.е. сама переменная не модифицируется, а только содержит исходную информацию.

2.      М — модифицируемые или создаваемые внутри программы переменные.

3.      С — переменные, участвующие в управлении работой программного модуля (управляющие переменные).

4.      Т — не используемые в программе (“паразитные”) переменные.

Поскольку каждая переменная может выполнять одновременно несколько функций, необходимо учитывать её в каждой соответствующей функциональной группе.

Далее вводится значение метрики Чепина:

                                                                              (8)

где  — весовые коэффициенты.

  Весовые коэффициенты в выражении (10) использованы для отражения различного влияния на сложность программы каждой функциональной группы. По мнению автора метрики, наибольший вес, равный трём, имеет функциональная группа С, т.к. она влияет на поток управления программы. Весовые коэффициенты остальных групп распределяются следующим образом:  Весовой коэффициент группы Т не равен нулю, поскольку “паразитные” переменные не увеличивают сложность потока данных программы, но иногда затрудняют её понимание. С учётом весовых коэффициентов выражение (10) принимает вид:

                                                                            (9)

Следует отметить, что рассмотренные метрики сложности программ основаны на анализе исходных текстов программ и графов программ, что обеспечивает единый подход к автоматизации их расчёта.

Метрика Кафура

Метрика такжеоснованная на учёте потока данных программы. Вводятся понятия локального и глобального потока:

Локальный поток информации из A в B существует, если:

1        Модуль А вызывает модуль В (прямой локальный поток)

2        Модуль В вызывает модуль А и А возвращает В значение, которое используется в В (непрямой локальный поток)

3        Модуль С вызывает модули А, В и передаёт результат выполнения модуля А в В

Глобальный поток информации из А в В через глобальную структуру данных D существует, если модуль А помещает информацию в D, а модуль В использует информацию из D. На основе этих понятий вводится величина I - информационная сложность процедуры:

                      I = length * (fan_in * fan_out)^2

Здесь:

   length - сложность текста процедуры (меряется через какую-нибудь из метрик объёма, типа метрик Холстеда, Маккейба, LOC и т.п.)

   fan_in - число локальных потоков внутрь процедуры плюс число структур данных, из которых процедура берёт информацию

   fan_out - число локальных потоков из процедуры плюс число структур данных, которые обновляются процедурой

Можно определить информационную сложность модуля как сумму информационных сложностей входящих в него процедур. Следующий шаг - рассмотреть информационную сложность модуля относительно некоторой структуры данных. Информационная мера сложности модуля относительно структуры данных:

                  J = W * R + W * WrRd + WrRd x R + WrRd * (WrRd - 1)

Здесь:

1        W - число процедур, которые только обновляют структуру данных;

2        R - Только читают информацию из структуры данных;

3        WrRd - и читают, и обновляют информацию в структуре данных
Следующая метрика позволяет посчитатьоценку уровня комментированности программы F:

                                          .                           (10)

где  — количество комментариев в программе; — количество строк или операторов исходного текста. Таким образом, метрика  отражает насыщенность программы комментариями.

Исходя из практического опыта, принято считать, что,  т.е. на каждые десять строк программы должен приходиться минимум один комментарий. Как показывают исследования, комментарий распределяются по тексту программы неравномерно: в начале программы их избыток, а в середине или конце — недостаток. Это объясняется тем, что в начале программы, как правило, расположены операторы описания идентификаторов, требующие более “плотного” комментирования. Кроме того, в начале программы также расположены “шапки”, содержащие общие сведения об исполнителе, характере, функциональном назначении программы и т.п. Такая насыщенность компенсирует недостаток комментариев в теле программы, и поэтому формула (10) недостаточно точно отражает комментированность функциональной части текста программы.

Более удачен вариант, когда вся программа разбивается на n равных сегментов и для каждого из них определяется :

                                                                   (11)

при этом:

                                                                                               (12)

Уровень комментированности программы считается нормальным, если выполняется условие: . В противном случае какой-либо фрагмент программы дополняется комментариями до номинального уровня.

Следующая метрика измеряет теоретическую длину программы  используя аппроксимирующую формулу:

                                                                 (13)

где  — словарь операторов;  — словарь операндов программы.

Вводя эту оценку, Холстед исходит из основных концепций теории информации, по аналогии, с которыми частота использования операторов и операндов в программе пропорциональна двоичному логарифму количества их типов. Таким образом, выражение (13) представляет собой идеализированную аппроксимацию (2), т.е. справедливо для потенциально корректных программ, свободных от избыточности или несовершенств (стилистических ошибок). Несовершенствами можно считать следующие ситуации:

1.      последующая операция уничтожает результаты предыдущей без их использования;

2.      присутствуют тождественные выражения, решающие совершенно одинаковые задачи;

3.      одной и той же переменной назначаются различные имена и т.п.

Подобные ситуации приводят к изменению  без изменения .

Для стилистически корректных программ отклонение в оценке теоретической длины  от реальной N не превышает 10%.

Метрики сложности

Помимо показателей оценки объема работ по проекту очень важными для получения объективных оценок по проекту являются показатели оценки его сложности. Как правило, данные показатели не могут быть вычислены на самых ранних стадиях работы над проектом, поскольку требуют, как минимум, детального проектирования. Однако эти показатели очень важны для получения прогнозных оценок длительности и стоимости проекта, поскольку непосредственно определяют его трудоемкость.

Объектно-ориентированные метрики

В современных условиях большинство программных проектов создается на основе ОО подхода, в связи с чем существует значительное количество метрик, позволяющих получить оценку сложности объектно-ориентированных проектов.

Метрика

Описание

Взвешенная насыщенность класса 1 (Weighted Methods Per Class (WMC)

Отражает относительную меру сложности класса на основе цикломатической сложности каждого его метода. Класс с более сложными методами и большим количеством методов считается более сложным. При вычислении метрики родительские классы не учитываются.

Взвешенная насыщенность класса 2 (Weighted Methods Per Class (WMC2))

Мера сложности класса, основанная на том, что класс с большим числом методов, является более сложным, и что метод с большим количеством параметров также является более сложным. При вычислении метрики родительские классы не учитываются.

Глубина дерева наследования (Depth of inheritance tree)

Длина самого длинного пути наследования, заканчивающегося на данном модуле. Чем глубже дерево наследования модуля, тем может оказаться сложнее предсказать его поведение. С другой стороны, увеличение глубины даёт больший потенциал повторного использования данным модулем поведения, определённого для классов-предков.

Связность объектов (Coupling between objects)

Количество модулей, связанных с данным модулем в роли клиента или поставщика. Чрезмерная связность говорит о слабости модульной инкапсуляции и может препятствовать повторному использованию кода.

Отклик на класс (Response For Class)

Количество методов, которые могут вызываться экземплярами класса; вычисляется как сумма количества локальных методов, так и количества удаленных методов




2 РАЗРАБОТКА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ







Листинг программы

program Project1;
uses

  Forms,

  Unit1 in 'Unit1.pas' {Form1},

  Unit2 in 'Unit2.pas' {Form2};
{$R *.res}
begin

  Application.Initialize;

  Application.CreateForm(TForm1, Form1);

  Application.CreateForm(TForm2, Form2);

  Application.Run;

end.
unit Unit1;
interface
uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

            Dialogs, StdCtrls, Unit2, math;
type

  TForm1 = class(TForm)

    Button1: TButton;

    Memo1: TMemo;

    OpenDialog1: TOpenDialog;

    Button2: TButton;

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;
type

            TOperatorInfo = record

                        n : string;

                        c : Integer;

            end;
const TABLE_OF_SEPARATORS : array[0..3] of TOperatorInfo =

            ((n:' ';c:0), (n:Chr(10);c:0), (n:Chr(13);c:0), (n:Chr(9);c:0));
var

            Form1: TForm1;

            tableOfFunctions : array of TOperatorInfo;

            tableOfVariables : array of TOperatorInfo;

            TABLE_OF_OPERATORS : array[0..20] of TOperatorInfo =

            ((n:'+';c:0), (n:'-';c:0), (n:'/';c:0), (n:'*';c:0), (n:';';c:0),

             (n:',';c:0), (n:':';c:0), (n:'=';c:0), (n:'^';c:0), (n:'>';c:0),

             (n:'<';c:0), (n:'.';c:0), (n:'@';c:0), (n:'(';c:0), (n:')';c:0),

             (n:'{';c:0), (n:'}';c:0), (n:'[';c:0), (n:']';c:0), (n:'''';c:0),

             (n:'"';c:0));

            TABLE_OF_KEWORDS : array[0..40] of TOperatorInfo =

            ((n:'div';c:0), (n:'mod';c:0), (n:'not';c:0), (n:'and';c:0), (n:'or';c:0),

             (n:'xor';c:0), (n:'shl';c:0), (n:'shr';c:0), (n:'in';c:0), (n:'is';c:0),

             (n:'not';c:0), (n:'while';c:0), (n:'do';c:0), (n:'begin';c:0), (n:'end';c:0),

             (n:'var';c:0), (n:'const';c:0), (n:'type';c:0), (n:'record';c:0), (n:'repeat';c:0),

             (n:'until';c:0), (n:'til';c:0), (n:'for';c:0), (n:'to';c:0), (n:'if';c:0),

             (n:'else';c:0), (n:'then';c:0), (n:'case';c:0), (n:'with';c:0),

             (n:'uses';c:0), (n:'goto';c:0), (n:'implementation';c:0), (n:'public';c:0),

             (n:'function';c:0), (n:'procedure';c:0), (n:'interface';c:0),

             (n:'private';c:0), (n:'array';c:0), (n:'of';c:0), (n:'class';c:0), (n:'unit';c:0));

            constCount : Integer;
function myIsOperator( name : String ) : Boolean;

function myIsFunction( name : String ) : Boolean;

function myIsConstant( name : String ) : Boolean;

function myIsVariable( name : String ) : Boolean;

function mySkipFirstSeparators( text : String; pos : Integer ) : Integer;

function myGetNextWord( text : String; Var pos : Integer ) : String;

procedure myAddFunction( text : String );

procedure myAddVariable( text : String );

procedure myRecognize( text : String );

procedure myAnalize();
implementation
uses StrUtils;
{$R *.dfm}
function myIsOperator( name : String ) : Boolean;

var

            i, l : Integer;

begin

            l := Length( TABLE_OF_OPERATORS ) - 1;

            for i := 0 to l do

                        if CompareText( TABLE_OF_OPERATORS[i].n, name ) = 0 then begin

                                   TABLE_OF_OPERATORS[i].c := TABLE_OF_OPERATORS[i].c + 1;

                                   Result := True;

                                   Exit;

                        end;
            l := Length( TABLE_OF_KEWORDS ) - 1;

            for i := 0 to l do

                        if CompareText( TABLE_OF_KEWORDS[i].n, name ) = 0 then begin

                                   TABLE_OF_KEWORDS[i].c := TABLE_OF_KEWORDS[i].c + 1;

                                  
Result := True;

                                   Exit;

                        end;

            Result := False;

end;
function myIsFunction( name : String ) : Boolean;

var

            i, l : Integer;

begin

            l := Length( tableOfFunctions ) - 1;

            for i := 0 to l do

                        if CompareText( tableOfFunctions[i].n, name ) = 0 then begin

                                   tableOfFunctions[i].c := tableOfFunctions[i].c + 1;

                                   Result := True;

                                   Exit;

                        end;

            Result := False;

end;
function myIsConstant( name : String ) : Boolean;

Var

            pos : Integer;

            tmp : Double;

begin

            Val( name, tmp, pos );

            if pos = 0 then begin

                        Result := true;

                        Inc( constCount );

            end else Result := False;

end;
function myIsVariable( name : String ) : Boolean;

var

            i, l : Integer;

begin

            l := Length( tableOfVariables ) - 1;

            for i := 0 to l do

                        if CompareText( tableOfVariables[i].n, name ) = 0 then begin

                                   tableOfVariables[i].c := tableOfVariables[i].c + 1;

                                   Result := True;

                                   Exit;

                        end;

            Result := False;

end;
function mySkipFirstSeparators( text : String; pos : Integer ) : Integer;

Var

            move : Boolean;

            i, j, l, lstr : integer;

begin

            l := Length( TABLE_OF_SEPARATORS ) - 1;         //количество сепараторов

            lstr := Length( text );                                                                           //длмна строки

            i := pos - 1;                                                                                                                //начало поиска

            move := true;                                                                                                             //условие продолжения поиска
            While move and ( i < lstr ) do begin

                        Inc( i );

                        for j := 0 to l do

                                   if text[i] = TABLE_OF_SEPARATORS[j].n then break;

                        if j > l then move := False;

            end;

            Result := i;

end;
function myGetNextWord( text : String; Var pos : Integer ) : String;

Var

            i, posSep, posOp, tmp, l : integer;

begin

            l := Length( TABLE_OF_SEPARATORS ) - 1;

            posSep := Length( text );

            posOp := posSep;

            Result := '';
            pos := mySkipFirstSeparators( text, pos );
            for i := 0 to l do begin

                        tmp := PosEx( TABLE_OF_SEPARATORS[i].n, text, pos );

                        if ( tmp < posSep ) and ( tmp > 0 ) then posSep := tmp;

            end;
            l := Length( TABLE_OF_OPERATORS ) - 1;

            for i := 0 to l do begin

                        tmp := PosEx( TABLE_OF_OPERATORS[i].n, text, pos );

                        if ( tmp < posOp ) and ( tmp > 0 ) then posOp := tmp;

            end;
            if posSep < posOp then begin

                        tmp := posSep - pos;

                        Result := MidStr( text, pos, tmp );

                        pos := posSep;

            end else if ( posOp = pos ) then begin

                        tmp := 1;

                        Result := MidStr( text, pos, tmp );

                        Inc(pos);

            end else begin

                        tmp := posOp - pos;

                        Result := MidStr( text, pos, tmp );

                        pos := posOp;

            end;

end;
procedure myAddFunction( text : String );

var

            l : Integer;

begin

            l := Length( tableOfFunctions );

            SetLength( tableOfFunctions, l + 1 );

            tableOfFunctions[l].n := text;

            tableOfFunctions[l].c := 1;

end;
procedure myAddVariable( text : String );

var

            l : Integer;

begin

            l := Length( tableOfVariables );

            SetLength( tableOfVariables, l + 1 );

            tableOfVariables[l].n := text;

            tableOfVariables[l].c := 1;

end;
procedure myRecognize( text : String );

var

            delMe: Boolean;

            len, curPos, tmp : Integer;

            element : String;

begin

            delMe := true;

            curPos := 1;

            len := Length( text );

            SetLength( tableOfFunctions, 0 );

            SetLength( tableOfVariables, 0 );

            element := '';
            while curPos <= len do begin

                        element := myGetNextWord( text, curPos );

                        if ( curPos > 933 ) and delMe then

                                   delMe := False;

                        if not ( myIsOperator( element ) or

                                                           myIsFunction( element ) or

                                                           myIsConstant( element ) or

                                                           myIsVariable( element ) ) then begin

                                   Form2.Edit1.Text := element;

                                   Form1.Memo1.SelStart := curPos;

                                   Form1.Memo1.SelLength := Length(element);

                                   if Form2.ShowModal() = mrOk then begin

                                               if Form2.RadioGroup1.ItemIndex = 0 then myAddFunction( element )

                                               else myAddVariable( element );

                                   end;

                        end;

            end;

end;
procedure myAnalize();

var

            i, l : Integer;

begin

            l := Length( tableOfVariables ) - 1;

            for i := 0 to l do

                        Inc( constCount, tableOfVariables[i].c );
//          Result := False;

end;
procedure TForm1.Button1Click(Sender: TObject);

begin

            if OpenDialog1.Execute() then begin

                        Memo1.Lines.LoadFromFile( OpenDialog1.FileName );

            end;

end;
procedure TForm1.Button2Click(Sender: TObject);

var

            i, n1, n2, nn, nn1, nn2, span : Integer;

            _nn : Double;

            str, name : String;

begin

            SetLength( tableOfFunctions, 0);

            SetLength( tableOfVariables, 0);

            for i:=0 to length(TABLE_OF_KEWORDS) - 1 do begin

                        TABLE_OF_KEWORDS[i].c := 0;

            end;

            for i:=0 to length(TABLE_OF_OPERATORS) - 1 do begin

                        TABLE_OF_OPERATORS[i].c := 0;

            end;
            str := Form1.Memo1.Lines.Text;

            myRecognize( str );
            n1 := Length(tableOfFunctions);

            nn1 := n1;

            for i:=0 to length(TABLE_OF_KEWORDS) - 1 do begin

                        Inc(nn1, TABLE_OF_KEWORDS[i].c);

                        if TABLE_OF_KEWORDS[i].c > 0 then Inc(n1);

            end;

            for i:=0 to length(TABLE_OF_OPERATORS) - 1 do begin

                        Inc(nn1, TABLE_OF_OPERATORS[i].c);

                        if TABLE_OF_OPERATORS[i].c > 0 then Inc(n1);

            end;

            n2 := 0;

            for i:=0 to length(tableOfVariables) - 1 do begin

                        if tableOfVariables[i].c > 0 then Inc(n2);

            end;

            nn2 := Length(tableOfVariables);
            span := 0;

            for i:=0 to length(tableOfVariables) - 1 do begin

                        if tableOfVariables[i].c > span then begin

                                   span := tableOfVariables[i].c;

                                   name := tableOfVariables[i].n;

                        end;

            end;

            for i:=0 to length(tableOfFunctions) - 1 do begin

                        if tableOfFunctions[i].c > span then begin

                                   span := tableOfFunctions[i].c;

                                   name := tableOfFunctions[i].n;

                        end;

            end;

            nn := nn1+nn2;

            _nn := n1 * log2(n1) + n2 * log2(n2);

            ShowMessage('Identifier ' + name + ' has SPAN= ' + IntToStr(span-1));

            ShowMessage('N=' + IntToStr(nn));

            ShowMessage('N''=' + FloatToStr( _nn ));

            ShowMessage('|N-N''|/N=' + FloatToStr( 100 * abs(nn-_nn) / nn ));

end;
end.
unit Unit2;
interface
uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, ExtCtrls;
type

  TForm2 = class(TForm)

    RadioGroup1: TRadioGroup;

    Button1: TButton;

    Edit1: TEdit;

    procedure Button1Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;
var

  Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);

begin

            ModalResult := mrOk;

end;
end.

1. Реферат Психологія між особистісних стосунків
2. Реферат на тему Antigone Essay Research Paper Fate Of A
3. Курсовая на тему Учет доходов и расходов от реализации
4. Курсовая на тему Учёт поступления и выбытия основных средств
5. Реферат Психологические аспекты управленческой деятельности
6. Реферат Электрооборудование станка 16Д25
7. Реферат на тему Операция Буря в пустыне
8. Диплом на тему Банкротство (несостоятельность) юридических лиц
9. Реферат Савельев, Николай Александрович генерал-лейтенант
10. Реферат Искусство эпохи Возрождения в Италии