В моем предыдущем вопросе о простоте, касающейся читабельности , было много ответов, которые помогли мне увидеть, что мое определение и понимание простоты в коде, возможно, было неверным.
Как я могу определить простоту в коде? Какие программные измерения и метрики доступны для измерения простоты кода?
code-quality
Ричард
источник
источник
Ответы:
Наиболее распространенными метриками для измерения сложности (или простоты, если принять простоту за противоположность сложности) являются цикломатическая сложность МакКейба и метрики сложности Холстеда .
Цикломатическая сложность измеряет количество различных путей в данной единице, обычно в методе или функции, хотя она также может быть вычислена в классе. По мере увеличения числа путей становится все труднее запоминать поток данных через данный модуль, что связано с концепцией рабочей памяти . Высокая цикломатическая сложность имеет тенденцию указывать на трудность в способности тестировать модуль - требуется больше тестовых случаев, чтобы покрыть различные пути через систему. Также были исследования, которые связывают высокую цикломатическую сложность с высокой частотой дефектов. Как правило, цикломатическая сложность 10 указывает на то, что единица должна быть проверена и, возможно, подвергнута рефакторингу.
Меры сложности Холстеда используют входные данные от общих и различных операторов и операндов для вычисления объема, сложности и усилия фрагмента кода. Сложность, которая представляет собой (количество уникальных операторов / 2) * (общее количество операндов / количество уникальных операндов), связана со способностью читать и понимать код для таких задач, как изучение системы или выполнение обзора кода. Опять же, вы можете посчитать это на системном уровне, уровне класса или уровне метода / функции. Есть несколько сообщений о том, как вычислить эти измерения здесь и здесь .
Простой подсчет строк кода также может дать представление о сложности. Больше строк кода означает, что в модуле есть что читать и понимать. Я не хотел бы использовать это как отдельное измерение. Вместо этого я бы использовал его с другими измерениями, такими как количество дефектов в данном модуле, чтобы получить плотность дефектов. Высокая плотность дефектов может указывать на проблемы при написании тестов и выполнении проверок кода, которые могут быть или не быть вызваны сложным кодом.
Разветвление и разветвление - это две другие метрики, связанные с потоком данных. Как определено здесь , fan in - это сумма вызванных процедур, считывание параметров, а считывание глобальных переменных и разветвление - это сумма процедур, вызывающих данную процедуру, записанных параметров (представленных внешним пользователям, переданных по ссылке), и глобальные переменные, записанные в. Опять же, высокий уровень разветвления и разветвления может указывать на модуль, который может быть трудным для понимания.
В определенных парадигмах могут быть другие меры или метрики, которые также полезны. Например, в объектно-ориентированном мире для оценки того, насколько проста или сложна система, можно использовать связывание мониторинга (желание меньше), сплоченность (желание высоко) и глубину наследования (желание низко).
Конечно, важно понимать, что многие показатели и показатели являются просто показателями. Вы должны использовать свое суждение, чтобы определить, нужно ли проводить рефакторинг для увеличения простоты или не стоит ли это делать. Вы можете выполнять измерения, вычислять метрики и узнавать о своем коде, но вы не хотите проектировать свою систему по числам. В конечном счете, делать то, что имеет смысл.
источник
Вместо того, чтобы смотреть на формальный способ определения простоты, я бы хотел определить простоту как атрибут качества написания кода.
Я не ставлю некоторую меру простоты, но когда вы называете что-то простое или нет.
1. Обход кода:
насколько легко перемещаться по коду? Легко ли определить, где написаны функции API? Легко ли понять потоки вызовов, например, какие методы вызывают другие (и почему) - реализованы ли хорошие конечные автоматы или четко определены алгоритмы?
Когда прохождение кода легко, за кодом просто следовать.
2. Присвоение имен
В то время как другие стандарты кодирования помогают сделать код более понятным, наиболее важным является присвоение имен классам / объектам-экземплярам / переменным / методам. Использование четкие и однозначные имена явно имеет большое влияние на простоте коды. Когда трудно определить простое имя, это признак того, что вы можете переосмыслить идею, являющуюся этой переменной / методом.
3. Интерпретация и ссылки.
Каждый из ваших методов играет определенную роль. Легко ли определить каждую переменную / атрибут, какую роль они играют? Когда часть кода делает что-то, что подразумевает допущения или влияет на несвязанный набор переменных, это может стать кошмаром обслуживания.
4. Зависимость или взаимосвязь.
Об этом сложно судить, просто взглянув на код, но становится очень очевидным, если кто-то пытается исправить ваши ошибки. Когда некоторые другие вещи изменяются в каком-то другом объекте, изменяется ли операция здесь? Эти изменения очевидны? Вам нужно менять API так часто, чтобы приспособить вещи? Это говорит о том, что межмодульные отношения не просты
5. Входные данные пользователя или приложения
Наконец, насколько просто пользовательские входные данные или приложение принимаются в API / UI? Когда вам нужно предоставить несколько возможных пользователей / приложений (для разных целей) - они очевидны? Существуют ли состояния / детали, которые не связаны с высшей абстракцией, но все же возвращаются к интерфейсу?
Простой вопрос, который я обычно задаю, заключается в следующем: если бы вместо программы я бы попросил человека выполнить ту же функцию, заполнил бы я эту информацию в бумажной форме ? Если нет, я не достаточно прост здесь.
Я не буду говорить, что этот список является исчерпывающим, но я думаю, что критерии - насколько легко или сложно использовать и модифицировать программное обеспечение. Это просто.
источник
Я не знаю каких-либо хороших существующих метрик для простоты кода (это не значит, что они не существуют - просто я не знаю о них). Я мог бы предложить некоторые, может быть, некоторые помогут:
Простота используемых языковых функций: если в языке есть функции, которые можно считать «продвинутыми» и «простыми», вы можете подсчитать количество появлений расширенных функций. То, как вы определяете «продвинутый», может быть немного более субъективным. Я предполагаю, что некоторые могут сказать, что это также похоже на измерение «умности» программы. Типичный пример: некоторые могут сказать, что
?:
оператор должен быть «продвинутой» функцией, другие могут не согласиться. Я не знаю, насколько легко было бы написать инструмент, который может проверить это.Простота конструкций внутри программы: вы можете измерить количество параметров, которые примет функция. Если у вас есть> п % всех функций с> м параметров, вы можете выбрать , чтобы считать это не просто, в зависимости от того, как вы определяете н и м (может быть , п = 3 и т = 6?). Я думаю, что есть некоторые инструменты статического анализа, которые могут это измерить - я думаю, что JTest просто измеряет функции с> m параметрами.
Вы можете попытаться посчитать количество вложенных циклов или управляющих структур. Это, я думаю, на самом деле не плохой показатель, и я думаю, что есть имя для него (не могу вспомнить с верху моей головы). Опять же, я думаю, что есть инструменты (опять же, как JTest), которые могут в определенной степени измерить это.
Вы можете попытаться измерить «рефакторируемость». Если ваш код содержит много фрагментов кода, которые могут быть реорганизованы, но это не так , возможно, это было бы не так просто. Я также вспоминаю со времени, когда я работал с JTest, он тоже пытался измерить это, но я помню, что не часто соглашался с этим в этом случае, поэтому YMMV.
Вы можете попытаться измерить количество слоев между различными частями вашей системы. Например: сколько различных частей кода будет касаться данных, которые поступают из веб-формы, прежде чем они будут сохранены в базе данных? Это может быть сложно измерить правильно ...
источник
?:
являются проблемой, когда они вложены в 5 глубин. Что касается слоев, то четко разделенные слои лучше, чем один извилистый слой. Но 7 в основном избыточных слоев, когда нужны были только 2 или 3, - это плохо.