МЕТРИКИ ОЦЕНКИ КАЧЕСТВА КОДА ДЛЯ АНАЛИЗА ПРЕИМУЩЕСТВ ПОДХОДА TDD В ОБРАЗОВАТЕЛЬНЫХ ПРОЕКТАХ
И.Е. Попова, студент Е.Д. Чиркова, студент А.А. Рогалев, ассистент Сибирский федеральный университет (Россия, г. Красноярск)
DOI: 10.24411/2500-1000-2020-10040
Аннотация. Данная работа посвящена исследованию способов оценки показателей качества кода, которые возможно применять в таких проектах. В статье освещается понятие разработки проектов через тестирование, рассматриваются различные оценки качества программного обеспечения, в том числе связность, сцепление и сложность, а также необходимые методы для их определения. Далее затрагивается тема автоматической оценки, к которой прибегают преподаватели при оценивании выполненных студентами работ.
Ключевые слова: TDD, система, оценка, образование, связность, сцепление, сложность, метрики.
Разработка через тестирование (TDD), несмотря на свое название, не является техникой тестирования, а скорее техникой разработки, в которой тесты пишутся до исходного кода [1]. Тесты добавляются постепенно, в процессе реализации. После их прохождения, код подвергается рефак-торингу для улучшения его внутренней структуры. Этот инкрементный цикл повторяется до тех пор, пока не будут реализованы все функциональные требования. Как литература, так и практика указывают на то, что использование TDD дает несколько преимуществ. TDD улучшает тестовое покрытие [2] и упрощает конструкцию, позволяя создавать системы с высокой мерой связи и слабой мерой сцепления [3]. TDD также позволяет более четко определить область реализации [3]. В качестве положительного побочного эффекта, TDD может приводить к повышению удовлетворенности работой и уверенности в себе разработчика [3]. С другой стороны, TDD подвергается критике за то, что он не компенсирует отсутствие предварительного проектирования и не очень подходит для таких систем, как программное обеспечение систем безопасности или многопоточные приложения, поскольку он не может механически продемонстрировать, что цели создания этих систем были дос-
тигнуты [4]. Также утверждается, что быстрые изменения могут привести к дорогостоящим сбоям в тестах и что отсутствие навыков применения или тестирования может привести к недостаточному охвату тестированием [5].
Одной из сфер, в которой применение TDD может оказать влияние на результативность процесса, является организация и ведение образовательных проектов по обучению программированию для студентов ИТ-специальностей. В работе Эдвар-дса [6] было проведено исследование, в котором установлено влияние подхода TDD на качество кода, разрабатываемого студентами. Группа студентов была обучена данной методике и выполняла задания с её использованием; до этого студенты выполняли задания, не применяя TDD. В результате тестирования c помощью автоматизированной системы оценивания было выявлено, что средний балл при использовании TDD вырос почти на 20%. При оценке работ студентов система использовала несколько показателей: оценки корректности кода, меру покрытия тестами кода и оценки завершенности и достоверности теста по отношению к задаче. Существуют и иные работы, в которых описывается процесс внедрения TDD и создания автоматизированной системы
поддержки внедрения TDD в образовательном процессе [7]. Однако анализ преимуществ, который данный подход может иметь в образовательном процессе, с одной стороны, в некоторых случаях не затрагивает проблему оценки качества программного обеспечения (ПО) с позиции оценки качества кода (показатели качества кода остаются вне поля зрения), с другой стороны - не учитывает специфики образовательных проектов при выборе анализируемых метрик [8]. Данная работа посвящена исследованию способов оценки показателей качества кода, которые возможно применять в таких проектах.
1. Оценка качества программного обеспечения
Для измерения качества программного обеспечения можно использовать ряд методов и показателей [9]. Программное обеспечение - это то, что видят пользователи, а код - это то, что видят программисты. Для некачественного кода характерно создание некачественного программного обеспечения, однако для высококачественного кода возможно создание программного обеспечения, которое пользователи не смогут использовать, и также возможно, что программное обеспечение, которое с удовольствием используют пользователи, для разработчиков может вызывать большие трудности при поддержке этого обеспечения. Если важно оценить качество кода, лучшим механизмом для этого должно быть не измерение качества программного обеспечения. Есть несколько способов измерить качество кода, наиболее значимые - вычисление специальных метрик. Эти метрики могут измерять основные показатели некачественного (плохого) кода: низкая связность, высокое сцепление и высокая сложность.
1.1. Связность. Низкий уровень связности делает код «плохим». Маклафлин и др. (из списка источников) определяют связность как степень, с которой элементы модуля взаимосвязаны. Хорошо спроектированный проект обладает функциональной связностью [10]. Он иллюстрирует типичную парадигму дизайна «делает одно и делает это хорошо». При низкой связности, как при сплошной сплоченности, код
в модуле становится сложным для восприятия, так как большая его часть не связана между собой. Кроме того, когда связность очень низкая, функционально связанные изменения потребуют изменений нескольких модулей, а не только одного. Низкая связность также затрудняет повторное использование модулей, потому что использование модуля с низким уровнем связность очень часто влечет за собой зависимость от дополнительного набора функций. Шах (из списка источников) объясняет, что высокая связность полезна, потому что код, обладающий такими свойствами, более удобен в использовании и обслуживании, и она обеспечивает изолирование неисправности в одном модуле [11]. Связность, по сути, является мерой организации - она измеряет, насколько согласованны все функции модуля. Далее рассмотрены несколько методов для измерения уровня связности.
1.1.1. Недостаточность связанных методов (Lack of Cohesion Methods). Одним из популярных методов оценки уровня связности является определение недостаточности связанных методов (LCOM), предложенных Чидамбером и Кемерером (из списка источников) [12]. Максимально связный класс должен иметь каждую переменную экземпляра, используемую каждым отдельным методом, определенным в классе. Класс, в котором одна из переменных не используется одним из методов, несколько менее связан, чем класс, в котором все переменные используются всеми методами. Имея это в виду, Чидамбер и Кемерер (из списка источников) предложили взять число непересекающихся множеств, образованных путем пересечения созданных множеств, взяв все переменные экземпляра, используемые каждым из методов в классе. Формальная спецификация для этой метрики состоит в том, что при заданном наборе методов {Mi} (i = 1, ..., m), обращающихся к набору атрибутов {Aj} (j = 1, ..., a), пусть число методов, обращающихся к каждому фрагменту данных, равно ц (Aj) и недостаточность связанных методов определяется следующим образом:
LCOM =
(|zr=iKAj))-m
(1)
m
1.1.2. Индекс специализации
(Specialization Index). Объектно-ориентированные системы позволяют реа-лизовывать полиморфизм. Полиморфизм -очень мощный инструмент, но разработчики иногда злоупотребляют им. Хорошие программы следуют тому, что Мартин (из списка источников) называет «принципом замены Лискова», - что означает, что подтипы легко заменяются на их базовые типы [13]. Нарушение этого принципа означает, что создается связь между классами, которая не является естественной. Это показатель низкой связности. Индекс специализации (SI), предложенный Лоренц и Кид (из списка источников), может использоваться для определения того, как эффективно подклассы реализуют новое поведение, используя существующее поведение. Это помогает определить качество подкласса и уровень связности в подклассах. Формула для вычисления индекса специализации (SI) с учетом дерева глубины наследования (DIT), количества переопределенных методов (NORM) и количества методов (NOM) определяется как:
SI =
DIT X NORM
NOM
2)
(
1.2. Сцепление. Еще одна причина ухудшения качества кода - высокая сте-
пень сцепления. Пейдж-Джонс (из списка источников) определяет сцепление как степень, в которой различные модули зависят друг от друга [14]. Высокая степень сцепления сама по себе не приводит к плохому коду, если один модуль может быть изменен и это не повлияет на работу другого модуля. В хорошо продуманной системе модули должны взаимодействовать с другими модулями. Проблемы возникают, когда один модуль полагается на внутреннюю структуру другого модуля. Тогда изменение одного модуля требует замены другого модуля. Приведем основные методы оценки сцепления.
1.2.1. Расстояние от главной последовательности (Distance from The Main Sequence)
Мартин (из списка источников) описывает стабильность пакета как «объем работы, необходимый для внесения изменений» [15]. Нестабильность пакета (I) можно определить по следующей формуле:
I =
Ся + Ср
(3)
где Са - афферентная связь, которая определяется для пакета как число классов вне этого пакета, зависящих от классов внутри него. Се - эфферентная связь, которая определяется как число классов, которые зависят от классов внутри нее, вне пакета.
Рисунок. Пример сцепления
В примере связи из рисунка с Са = 3, Се = 1 и нестабильностью I = 1/4. Когда I = 1, пакеты не зависят от рассматриваемого пакета, но сам пакет зависит от других.
Это очень «нестабильная» ситуация. Когда I = 0, пакет сильно зависит от других, но не имеет собственных зависимостей. Это называется «стабильным», поскольку ма-
ловероятно, что пакет будет иметь много изменений со временем. Поскольку пакет зависит от других, изменить его очень сложно. В стабильных или нестабильных пакетах нет ничего плохого, если они соответствуют определенному критерию -согласно Мартину (из списка источников), они настолько абстрактны, насколько стабильны [16]. Смысл этого в том, что стабильные пакеты должны быть абстрактны, т.е. легко расширяемы. Мартин (из списка источников) предлагает метрику для измерения абстрактности пакета (А):
Na
a = n?
(4)
где общее количество классов в пакете - Nc, и количество абстрактных классов или интерфейсов в пакете - Na.
1.3. Cложность. Наконец, одна из наиболее распространенных причин, по которой код считается плохим - это сложность кода. Сложность кода - «количество усилий, необходимых для правильного понимания и изменения кода» [11]. Многие вещи могут способствовать сложности модуля или класса. Код может быть сложным, если в одном методе слишком много строк кода или слишком много строк кода в самом модуле, код плохо закомментирован или комментарии вводят в заблуждение, а также, когда в коде слишком много операторов ветвления. Код сложен, когда имена переменных слишком короткие или не описательные. Сложность немного более расплывчата, чем сцепление и связность, поэтому, естественно, ее несколько более затруднительно оценивать. Тем не менее, существуют некоторые (несовершенные) метрики, которые помогают определить, является ли проект чересчур сложным.
1.3.1. Размер методов и классов (Size of Methods and Classes)
Измерение методов и классов - это относительно простой процесс, так как количество строк в коде можно легко измерить. Однако комментарии и пробелы помогают сделать код более понятным, поэтому их не следует учитывать в метриках, основанных на размере.
1.3.2. Цикломатическая Сложность Маккейба (McCabe Cyclomatic Complexity)
Чем больше выражений if, else, for и while внутри блока кода, тем он сложнее. Цикломатическая сложность блока кода — это, по сути, количество возможных путей управления через этот код. Формально цикломатическая сложность McCabe блока кода предполагает существование ориентированного графа, в котором каждое утверждение представляется как узел, а каждая возможность для потока управления переходить от одного оператора к другому представляется как ребро. Если E - это число ребер, N - это количество узлов, а P - это число независимых подграфов, то MCC определяется как:
МСС = Е - N + Р.
(5)
Метрика МСС чрезвычайно полезна для оценки относительной структурной сложности методов и других блоков кода, поэтому она остается одной из самых популярных метрик программного обеспечения, используемых сегодня.
1.3.3. Глубина вложенного блока (Nested Block Depth). Метрика «Глубина вложенных блоков» (NBD) измеряет уровень вложенности в коде. Это очень важно, т.к. чем больше уровней вложенности в модуле, тем сложнее его анализировать.
2. Автоматическая оценка проектов. Теперь рассмотрим пути внедрения TDD в образовательном процессе. При оценивании выполненных студентами работ преподаватели могут прибегать к ручной оценке или же автоматической. Существующие автоматизированные системы фокусируются на традиционном представлении об оценке программы - действительно ли представление учащихся «дает правильный результат». Из-за этого студенты в первую очередь уделяют внимание правильности результатов в контексте прохождения предложенных им тестов; все остальное в лучшем случае уходит на второй план (дизайн, комментирование, правильное использование абстракции, тестирование собственного кода и т.д.). На практике студенты самостоятельно проводят мень-
ше тестов. Чтобы использовать TDD в образовании, необходимо решить проблемы, с которыми сталкиваются существующие автоматизированные системы оценок. Web-CAT, веб-центр автоматизированного тестирования, - это прототип, разработанный в Virginia Tech для этой цели. Грейдер Web-CAT оценивает код ученика и тесты ученика вместе, требуя, чтобы они присутствовали в каждой заявке [17]. Он возлагает бремя демонстрации правильности на студента, а затем использует формулу оценки, которая фокусируется на тестировании производительности. Оценщик Web-CAT формирует оценки результата с использованием трех показателей: оценки корректности кода, меру покрытия тестами кода и оценки завершенности и достоверности теста по отношению к задаче.
Чтобы дать учащимся возможность использовать свои собственные возможности тестирования, оценка корректности кода основана исключительно на том, сколько собственных тестов студента может пройти представленный код. Мера покрытия тестами кода показывает, насколько тщательно тесты учащегося охватывают его код. Она может вычисляться на основе критериев покрытия методов, покрытия операторов, покрытия решений или некоторой их комбинации. Данные об охвате собираются по мере проведения студенческих тестов Оценка полноты и достоверности теста по отношению к задаче показывает, насколько тщательно тесты учащегося охватывают поставленную задачу (на основе сравнения с тестами, представленными разработчиками задания). Чтобы поддерживать быстрый цикл между написанием отдельных тестов и добавлением небольших фрагментов кода, что характерно для TDD, Web-CAT Grader позволяет неограниченное количество заявок от студентов вплоть до крайнего срока выполнения проекта. Студенты могут получать отзывы в любое время, так часто, как они хотят. Однако правильность их программ оценивается только по написанным ими тестам, поэтому, чтобы узнать больше об ошибках в своих программах, студент должен написать соответствующие тестовые примеры.
Данное решение не позволяет анализировать влияние TDD на итоговое качество созданного кода и, как следствие, успешность внедрения этого подхода в образовательном процессе. Исследования ряда авторов более глобально оценивают влияние подхода TDD на код [18].
Одно из самых главных преимуществ -это повышение уровня надежности системы, а также скорость разработки, уверенность в правильности работы кода, большие системы становятся более управляемыми, за счет разделения их на мелкие части. Кроме этого, упрощается документирование проектов. Из всего этого можно сделать вывод, что, анализ должен быть более глубокий.
Заключение. Таким образом, включение средств, позволяющих вычислять метрики качества кода в системы автоматизированного оценивания, представляется целесообразной. Однако необходимо учитывать специфику образовательных проектов для того, чтобы среди многообразия существующих метрик выбрать наиболее полезные для анализа. Характерные особенности проектов, разрабатываемых в образовательных целях - такие, как простая архитектура и малое количество модулей -могут приводиться к тому, что метрики, оценивающие сцепление, могут быть неустойчивы к даже небольшому изменению в архитектуре и коде проекта. Так, например, метрика I (нестабильность модуля) изменится на 100% от своего значения для примера на рисунке, в случае ликвидирования влияния модуля С на модуль D. Такая неустойчивость может привести к значительным погрешностям в интегральном оценивании качества кода для групп проектов.
С учетом рассмотренных выше методик оценки качества программного обеспечения, и специфики проектов, которые являются целью оценки, представляется оптимальным использовать метрики для измерения уровня связности и сложности, а именно: для связности - LCOM и SI, для сложности кода - MCC, Size Of Method, Size Of Class b NBD.
Библиографический список
1. BeckK. Test-Driven Development by Example. - Boston: Addison-Wesley, 2003. - 239 c.
2. Astels D. Test-Driven Development: A Practical Guide. - New Jersey: Prentice Hall, 2003.
3. Beck K. Aim, fire // IEEE Software. - 2001. - №18 (5). - C. 87-89.
4. Stephens M., Rosenberg D. Extreme Programming Refactored: The Case Against XP. -Berkeley: Aepress, 2003.
5. Boehm B., R. Turner. Balancing Agility and Discipline: A Guide for the Perplexed. - Boston: Addison-Wesley, 2004.
6. Stephen H. Edwards. Using Software Testing to Move Students from Trial-and Error to Re-flection-in-Action // ACM SIGCSE Bulletin. - 2004. - №36 (1). - C. 26-30.
7. Spacco J., Pugh W. Helping students appreciate test-driven development (TDD) // OOPSLA. 2006.
8. Janzen D.S., Saiedian H. On the Influence of Test-Driven Development on Software Design // Software Engineering Education Conference, Proceedings. 2006. C. 141-148.
9. Jones C. Applied software measurement. New York : McGraw-Hill Osborne Media, 2008.
10. McLaughlin B. D., Pollice G., West D. Head first object-oriented analysis and design. Sebastopol : O'Reilly Media, 2006.
11. Schach, S. Object-oriented and classical software engineering. New York : McGraw-Hill, 2006.
12. Chidamber S.R., Kemerer, C.F. Towards a metrics suite for object-oriented design // OOPSLA: Conference proceedings on Object-oriented programming systems, languages, and applications. - 1991. - № 91. - C. 197-211.
13. Hilton R. Quantitatively Evaluating Test-Driven Development by Applying Object-Oriented Quality Metrics to Open Source Projects. Denver. 2009.
14. Page-Jones M. Fundamentals of object-oriented design in UML. Boston : Addison-Wesley Professional, 1999.
15. Martin R.C. Agile software development, principles, patterns, and practices. New Jersey: Prentice Hall PTR, 2002. C. 7-30.
16. Martin R.C. Object-Oriented design quality metrics, an analysis of dependencies. 1994. C. 27-29.
17. Edwards S.H. Rethinking computer science education from a test-first perspective // Addendum to the 2003 Proc. Conf. Object-oriented Programming, Systems, Languages, and Applications, ACM. 2003.
18. Siniaalto M., Abrahamsson P. A Comparative Case Study on the Impact of Test-Driven Development on Program Design and Test Coverage // IEEE. 2007.
CODE QUALITY METRICS FOR ANALYZING THE BENEFITS OF THE TDD APPROACH IN EDUCATIONAL PROJECTS
I.E. Popova, Student E.D. Chirkova, Student A.A. Rogalev, Assistant Siberian Federal University (Russia, Krasnoyarsk)
Abstract. This work is devoted to the study of ways to assess the quality of code that can be used in such projects. The article covers the concept of project development through testing, discusses various assessments of software quality, including cohesion, coupling and complexity, as well as the necessary methods for determining them. Next, the topic of automatic assessment, which is resorted to by teachers when evaluating the work performed by students.
Keywords: TDD, system, assessment, education, cohesion, coupling, complexity, metrics.