Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
11
Добавлен:
10.02.2016
Размер:
53.4 Кб
Скачать

Министерство образования, науки, молодежи и спорта Украины

Одесский национальный политехнический университет

Институт компьютерных систем

Кафедра информационных систем

Лабораторная работа № 4

По дисциплине: «Качество и надёжность»

На тему: «Расчёт метрик проекта»

Выполнил:

ст. гр. АИ-091

Подкошин А.С.

Проверил:

Трофимов Б.Ф.

Одесса, 2013

Цель работы: для Open Source проекта из лабораторной работы №3 необходимо выполнить расчет следующих метрик:

* LOC (lines of code)

* average LPM (lines per method)

* max LPM (lines per method)

* average LPM (lines per class)

* max LPM (lines per class)

* max Depth of inheritance

* max Ciclomatic complexity

* average Ciclomatic complexity

* Unit test coverage.

* Total amount of user classes

* Total amount of user interfaces

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

Ход работы

1. Выбрал Open Source проект библиотеки high-scale-lib на Github https://github.com/boundary/high-scale-lib.

2. Установил плагин для измерения метрик CodePro AnalytiX для Eclipse от Google Developers.

3. Для измерения покрытия кода тестами я использовал плагин Cobertura.

3. Замерил следующие метрики:

LOC (Lines of code)

4,918

Average LPM (lines per method)

7.12

Max LPM (lines per method)

61

Min LPM (lines per method)

1

Average LPC (lines per class)

213.82

Max LPC (lines per class)

592

Max depth of inheritance

3

Average depth of inheritance

1.5

max Ciclomatic complexity

36

average Ciclomatic complexity

2.31

Unit test coverage

58%

Total amount of user classes

64

Total amount of user interfaces

2

4. Сгенерировал HTML Report средствами плагина CodePro AnalytiX.

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

Количество интерфейсов несоизмеримо с числом классов. Из этого можно сделать вывод о нарушении принципа Interface Segregation Principle(ISP). Возникнуть трудности в расширении поведения классов и ограничения доступа к методам класса.

Явно превышено число строк кода на один класс (213 строк). Значит, следовало бы разбить на более мелкие подклассы, т.е. провести декомпозицию на более низком уровне. Так, как большое число строк кода в классе усложняет его модифицирование, повышает вероятность нарушения принципа Open Closed Principle.

Максимальная цикломатическая сложность имеет большое значение (36). Что говорит, что существует некоторый метод с большим количеством возможных разветвлений в коде. Это значительно осложняет тестирование. Необходимо разбить метод на подметоды и вызывать их по очереди в основном методе.

Показатель покрытия кода тестами не очень большой, что не удивительно из-за предыдущих найденных нарушений. Кроме того тесты выполняются заметно долго (8,762 сек на 6 тестов).

6. Провёл статический анализ программного кода проекта при помощи средства FindBugs. Для этого установил соответствующий плагин для Eclipse.

Пять наиболее значимых ошибок:

1) Dead store to origlength in java.util.Hashtable.readObject(ObjectInputStream) ["java.util.Hashtable"] At Hashtable.java:[lines 36-91]

Причина появления: неиспользуемая переменная.

Решение: удалить переменную.

2) Unread field: java.util.Hashtable.loadFactor; should this field be static? ["java.util.Hashtable"] At Hashtable.java:[lines 36-91]

Участок кода, где зафиксирован bug:

private final float loadFactor = 0.75f;

private int threshold = (int)(loadFactor*4.0f);

public Hashtable() { super(); }

public Hashtable(int initialCapacity) { super(initialCapacity); }

public Hashtable(int initialCapacity, float loadFactor) {

super(initialCapacity);

if (!(loadFactor > 0) )

throw new IllegalArgumentException();

threshold = (int)(initialCapacity * loadFactor);

}

Причина появления: Пропущен модификатор static в объявлении константы.

Решение: добавить модификатор static.

3) Load of known null value in org.cliffc.high_scale_lib.NonBlockingHashMap.remove(Object, Object) ["org.cliffc.high_scale_lib.NonBlockingHashMap"] At NonBlockingHashMap.java:[lines 74-1293]

Участок кода, где зафиксирован bug:

/** Atomically do a {@link #remove(Object)} if-and-only-if the key is mapped

* to a value which is <code>equals</code> to the given value.

* @throws NullPointerException if the specified key or value is null */

public boolean remove( Object key,Object val )

{ return putIfMatch( key,TOMBSTONE, val ) == val; }

Причина появления: FindBugs сообщает, что значение параметра может быть null и что разработчик знает об этом, так нету проверки на null.

4) org.cliffc.high_scale_lib.NonBlockingHashMap.clone() makes inefficient use of keySet iterator instead of entrySet iterator ["org.cliffc.high_scale_lib.NonBlockingHashMap"] At NonBlockingHashMap.java:[lines 74-1293]

Участок кода где зафиксирован bug:

@Override

public Object clone() {

try {

. . . . .

// Now copy sanely

for( TypeK K : keySet() ) {

final TypeV V = get(K); // Do an official 'get'

t.put(K,V);

}

return t;

} catch (CloneNotSupportedException e) {

// this shouldn't happen, since we are Cloneable

throw new InternalError();

}

}

Причина появления: Неэффективное получение ключа и значения из HashMap. Сначала из HashMap извлекается список всех ключей, а потом по ним итеративно осуществляется доступ к значению HashMap.

Решение: использовать entrySet iterator и модифицировать код, как приведено ниже:

for ( Map.Entry< TypeK, TypeV > entry : entrySet() ) {

t.put(entry.getKey(), entry.getValue());

}

5) Comparison of String objects using == or != in org.cliffc.high_scale_lib.NonBlockingHashSet.add(Object) ["org.cliffc.high_scale_lib.NonBlockingHashSet"] At NonBlockingHashSet.java:[lines 21-83]

Участок кода, где зафиксирован bug:

public class NonBlockingHashSet<E> extends AbstractSet<E> implements Serializable {

private static final Object V = "";

. . . .

public boolean add ( final E o ) { return _map.putIfAbsent(o,V) != V; }

}

public TypeV putIfAbsent( TypeK key, TypeV val )

{

return putIfMatch( key, val, TOMBSTONЕ );

}

private static final Object TOMBSTONE = new Object();

private final TypeV putIfMatch( Object key, Object newVal, Object oldVal ) {

if (oldVal == null || newVal == null) throw new NullPointerException();

final Object res = putIfMatch( this, _kvs, key, newVal, oldVal );

assert !(res instanceof Prime);

assert res != null;

return res == TOMBSTONE ? null : (TypeV)res;

}

Причина появления: некорректное сравнение строк с использованием операторов = и !=. В данном случае объекты типа строки будут сравниваться по ссылкам, а не по значению.

Решение: использовать метод equals(Object) для сравнения объектов.

Выводы: в ходе выполнения данной лабораторной работы я провёл измерение метрик проекта на GitHub и по их значениям выявил некоторые нарушения в программном коде проекта. Метрики являются необходимым средством для анализа программного кода, но не достаточным. Иными словами, если показатели метрик плохие, то можно определённо сказать что и где не так. Но если показатели метрик находятся в допустимых значениях, то нельзя утверждать что код не содержит ошибок и нарушений.

Соседние файлы в папке Трофимов