Сравнительный анализ проектов с точки зрения недостатка сцепления методов в классах

02 октября 2016

Обзор

LCOM (Lack Of Cohesion of Methods) - набор метрик, которые показывают насколько методы класса не связаны друг с другом через свойства (атрибуты), проблемные классы имеют высокие значения LCOM.

LCOM1 = P

LCOM2 = P - Q,

где P - число пар методов в классе, которые не разделяют ни одного атрибута

Q - число пар методов в классе, которые разделяют хотя бы один атрибут.

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

С помощью Qualiter можно мониторить динамику изменения следующих метрик проекта:

  1. Средний LCOM1 для классов
  2. Средний LCOM2 для классов

Демонстрационные проекты

Для демонстрации эффективности мониторинга LCOM2 для выявления хорошей и плохой практик программирования мы добавили в open.qualiter.ru два проекта: demo-good-practice и demo-bad-practice

В проекте demo-bad-practice реализована плохая практика. Функционалы кэширования, вычисления распределения некоторой величины, загрузки контента по url и вычисления свободной памяти реализованы в классе Utils.

public class Utils {

    private static final Map cache = new HashMap<>();

    public static void chachePut(String key, Object obj) {
        cache.put(key, obj);
    }

    public static Object chacheGet(String key) {
        return cache.get(key);
    }

    public static void clearCache() {
        cache.clear();
    }

    public static String loadUrl(String url) throws MalformedURLException, IOException {

        URL website = new URL(url);
        URLConnection connection = website.openConnection();
        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));

        StringBuilder response = new StringBuilder();
        String inputLine;

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }

        in.close();

        return response.toString();
    }

    public static List calcDistribution(List dist, int step) {

        List res = new ArrayList<>();

        for (int from = 0; from <= Collections.max(dist); from = from + step) {
            DistributionPoint point = new DistributionPoint();
            point.setFrom(from);
            point.setTo(from + step);

            int y = 0;
            for (int i : dist) {
                if (i > from && i < from + step) {
                    y++;
                }
            }
            point.setValue(y);
            res.add(point);
        }

        return res;
    }

    public static Long getUsedMemory() {

        Runtime rt = Runtime.getRuntime();
        long totalMemory = rt.totalMemory();
        long freeMemory = rt.freeMemory();
        long usedMB = (totalMemory - freeMemory) / 1024 / 1024;

        return usedMB;
    }
}
    

В проекте demo-good-practice реализована хорошая практика. Каждый из вышеперечисленных функционалов реализована в отдельных классах: src/main/java/demo/utils/Cache.java, src/main/java/demo/utils/Distribution.java, src/main/java/demo/utils/Mem.java, src/main/java/demo/utils/Net.java.

В остальном проекты demo-bad-practice и demo-good-practice одинаковы. В проекте demo-bad-practice LCOM2 для класса Utils равен 15, средний LCOM2 всего проекта равен 6.25. Средний LCOM2 проекта demo-good-practice равен 1.86. Т.е. проект с плохой практикой программирования имеет больший средний недостаток сцепления методов в классах. В примере demo-bad-practice высокий недостаток сцепления методов в классе Utils возник из за того что в классе объединен слишком разнотипный функционал, соответственно класс необходимо разделить на несколько, так как это и было сделано в примере demo-good-practice

Вывод

Высокий средний недостаток сцепления методов классов проекта или высокая динамика его роста (см. рис 1) может говорить об том, что некоторые классы необходимо разделить на несколько, т.е. в некоторых классах объединен слишком разнотипный функционал. Какой конкретно класс имеет высокий недостаток сцепления методов в Qialiter View можно посмотреть в списке файлов для конкретной git ревизии с помощью сортировки по LCOM2.

Рис 1. Демонстрация высокой динамики роста среднего недостатка сцепления методов в классах проекта со временем с помощью Qualiter.

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

Рис 2. Демонстрация относительно слабой динамики изменения среднего недостатка сцепления методов в классах проекта со временем.

Литература

  1. Chidamber, S.R.; Kemerer, C.F. IEEE Transactions on Software Engineering Volume 20, Issue 6, Jun 1994 Page(s):476 - 493

Новости

  • Релиз Qualiter 4.5.0. Произведена интеграция с платформой SonarQube
    30 января 2019
  • Релиз Qualiter 3.1.0. Добавили Rest API.
    04 сентября 2018
  • Релиз Qualiter 3.0.3. Утилита для оценки необходимости рефакторинга компиляционной единицы Java кода. Доступно онлайн Demo.
    16 июля 2018
Все новости