
ЛР7_ОКиТПО
.docxМустафин А. А. ПРО-332Б.
Лабораторная работа 7.
«Оценка качества ПО на основе объектно-ориентированных метрик»
Оценка характеристики
с помощью метрик Мартина.
В предлагаемых задачах необходимо разработать программу, реализующую решение по приведенному условию, а затем оценить характеристики разработанной программы на основе применения объектно-ориентированных метрик Мартина.
Вариант 3. Определить понятие «Точка». Состояние объекта определяется следующими полями:
Координата по оси абсцисс (вещественное число);
Координата по оси ординат (вещественное число).
Базируясь на понятии «Точка», определить понятие «Квадрат». Квадрат определить через точку, соответствующую ее левому верхнему углу, и размер стороны квадрата. Проверить попадание точки в квадрат.
Реализация программы на языке С++:
Номер строк |
Строки программы |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include <iostream>
class Point { float x; // координата по оси абсцисс float y; // координата по оси ординат public: Point(float x, float y) : x(x), y(y) {}
float getX() const { return x; }
float getY() const { return y; } };
class Square { Point topLeft; // левый верхний угол квадрата float sideLength; // длина стороны квадрата public: Square(const Point& topLeft, float sideLength) : topLeft(topLeft), sideLength(sideLength) {}
bool pointInside(const Point& point) const { float pointX = point.getX(); float pointY = point.getY();
float topLeftX = topLeft.getX(); float topLeftY = topLeft.getY(); float bottomRightX = topLeftX + sideLength; float bottomRightY = topLeftY + sideLength;
return pointX >= topLeftX && pointX <= bottomRightX && pointY >= topLeftY && pointY <= bottomRightY; } };
int main() { setlocale(LC_ALL, "Rus"); // создаем точку и квадрат Point point(2.5, 3.5); Square square(Point(1.0, 1.0), 5.0);
// проверяем попадание точки в квадрат if (square.pointInside(point)) { std::cout << "Точка попадает в квадрат" << std::endl; } else { std::cout << "Точка не попадает в квадрат" << std::endl; }
return 0; } |
Исходный код программы включает три класса, который можно отнести к одной категории, предназначенной для решения задачи. К ним относятся следующие классы:
class Point – содержит поля для координаты по оси абсцисс и ординат.
class Square – имеет поля для левого верхнего угла квадрата и размера стороны.
Необходимо отметить, что классы, не входящие в рассматриваемую категорию, никак не зависят от ее классов. Следовательно, центростремительное сцепление Ca = 0. Нулевое значение метрики определяет полную независимость классов других категорий, не связанных с изменением частоты вещания радиостанции.
В классе Square используется вызов методов из класса Point (строка 26, 27, 29, 30). Таким образом, данный класс имеет зависимость от классов вне категории. Поэтому центробежное сцепление Ce = 1.
Исходя из полученного значения следует, что категория классов является максимально нестабильной, так как зависимость от других категорий носит преобладающий характер.
Определим меру абстрактности A рассматриваемой категории классов.
Код программы не содержит ни одного абстрактного класса, следовательно, nA=0. Общее кол-во классов в рассматриваемой категории составляет 2, следовательно, nAll=2.
Исходя из значения метрики A = 0 можно сделать вывод, что рассматриваемая категория классов является полностью конкретной.
Расстояние от главной последовательности определяется уравнением I+A-1. В соответствии с теорией Мартина расстояние до главной последовательности определяется по формуле:
Категория расположена на прямой главной последовательности, что свидетельствует о наилучшей сбалансированности между абстрактностью и нестабильностью.
Нормализованное расстояние до главной последовательности равно:
Вывод:
В целом качество разработанной программы можно считать достаточно высоким, так как рассматриваемая категория класса исходного кода находится в пределах нормализованного расстояния до главной последовательности.
Оценка характеристики
с помощью метрик Чидамбера и Кемерера.
В предлагаемой задаче необходимо разработать программу, реализующую решение по приведенному условию, а затем оценить характеристики разработанной программы на основе применения объектно-ориентированных метрик Чидамбера и Кемерера.
Вариант 6. Определить понятие «Автомобиль». Состояние объекта определяется следующими полями:
Регистрационный номер (строка из 6 символов);
Код региона России (целое число);
Год выпуска (целое число);
Фамилия владельца (строка до 20 символов).
В таблице регистрации автомобилей по заданному регистрационному номеру и коду региона изменить фамилию владельца на значение «Петровский».
Реализация программы на языке C++:
Номер строк |
Строки программы |
1 2 3
4 5 6 7 8 9 10 11 12
13 14
15 16 17 18 19 20
21 22 23
24 25 26
27 28 29
30 31 32
33 34 35
36 37 38 39
40 41 42
43 44 45 46
47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63 64 65
66 67
68 69
70 71
72 73
74
75 76
77 78 79 |
using System;
class Car { public string RegistrationNumber { get; set; } public int RegionCode { get; set; } public int YearOfManufacture { get; set; } public string OwnerLastName { get; set; }
public Car(string regNumber, int regionCode, int year, string ownerLastName) { RegistrationNumber = regNumber; RegionCode = regionCode; YearOfManufacture = year; OwnerLastName = ownerLastName; } }
class CarManager { public Car[] cars; private int currentIndex;
public CarManager(int size) { cars = new Car[size]; currentIndex = 0; }
public void AddCar(Car car) { if (currentIndex < cars.Length) { cars[currentIndex] = car; currentIndex++; Console.WriteLine("Автомобиль успешно добавлен."); } else { Console.WriteLine("Невозможно добавить больше автомобилей. Массив заполнен."); } }
public void ChangeOwnerLastName(string regNumber, int regionCode) { foreach (Car car in cars) { if (car != null && car.RegistrationNumber == regNumber && car.RegionCode == regionCode) { car.OwnerLastName = "Петровский"; Console.WriteLine($"Фамилия владельца изменена на 'Петровский' для автомобиля с регистрационным номером {car.RegistrationNumber} и кодом региона {car.RegionCode}."); return; } } Console.WriteLine("Автомобиль не найден."); } }
class Program { static void Main() { CarManager collection = new CarManager(2);
collection.AddCar(new Car("Х777АМ", 77, 2022, "Иванов")); collection.AddCar(new Car("Е111КК", 02, 2018, "Петров"));
Console.WriteLine("Изначальные данные об автомобилях:"); foreach (Car car in collection.cars) { if (car != null) { Console.WriteLine($"Рег. номер - {car.RegistrationNumber}, Код региона - {car.RegionCode}, Год выпуска - {car.YearOfManufacture}, Фамилия владельца - {car.OwnerLastName}"); } }
collection.ChangeOwnerLastName("ABC123", 77); collection.ChangeOwnerLastName("XYZ789", 50);
Console.WriteLine("\nОбновленные данные об автомобилях:"); foreach (Car car in collection.cars) { if (car != null) { Console.WriteLine($"Рег. номер - {car.RegistrationNumber}, Код региона - {car.RegionCode}, Год выпуска - {car.YearOfManufacture}, Фамилия владельца - {car.OwnerLastName}"); } } } } |
Оценка характеристик программы
Метрики С. Чидамбера и К. Кемерера
Исходный код программы содержит 3 класса:
class Car – Класс, определяющий понятие «Автомобиль».
class CarManager – Класс, отвечающий за управление массивом автомобилей и функцию замены фамилии.
class Program – основной класс программы.
Класс Car содержит 1 метод(конструктор).
NM(Car) = 1
Исходный код метода Car() содержит 7 строк.
WMC(Car) = 7
Класс CarManager содержит 3 метода, включая конструктор.
NM(CarManager) = 3
Исходный код метода CarManager() содержит 5 строк.
Исходный код метода AddCar() содержит 13 строк.
Исходный код метода ChangeOwnerLastName() содержит 14 строк.
WMC(CarManager) = 5+13+14 = 33.
Класс Program содержит 1 метод.
NM(Program) = 1
Исходный код метода Main() содержит 31 строку.
WMC(Program) = 31
Наиболее сложный класс по метрике WMC – CarManager.
Программа содержит один базовый класс Car, следовательно глубина дерева наследования DIT = 0. Количество классов потомков NOC = 0.
В классе Car наблюдается 0 обращений к методам других классов. Связность между классами объектов CBO = 0.
В классе CarManager наблюдается 5 обращений к методам других классов. Связность между классами объектов CBO = 5.
В классе Program наблюдается 11 обращений к методам других классов. Связность между классами объектов CBO = 11.
Наиболее сложным по связности является класс Program.
Определим количество откликов на класс RFC.
Для класса Car, R = 0, M = 1. Следовательно количество откликов на класс RFC = 0 + 1 = 1.
Для класса CarManager, R = 5, M = 3. Следовательно количество откликов на класс RFC = 5 + 3 = 8.
Для класса Program, R = 5, M = 3. Следовательно количество откликов на класс RFC = 11 + 1 = 12.
Исходя из полученных значений метрик RFC, наиболее сложным является класс Program.
Определим значение метрики отсутствия сцепления в методах LCOM.
Класс Car. Определен только один метод. LCOM = 0.
Класс CarManager. LCOM = 0 – 3 = 0.
Класс Program. Определен только один метод. LCOM = 0.
Вывод
Из анализа метрик следует, что сложность используемых классов невысокая, связность методов в классах – средняя. Чувствительность программы к модификации классов не высокая. Можно считать качество программы соответствующим среднему уровню.