Условное ведение журнала с минимальной цикломатической сложностью - PullRequest
62 голосов
/ 20 сентября 2008

Прочитав « Каков ваш / хороший предел для цикломатической сложности? », я понимаю, что многие мои коллеги были весьма недовольны этой новой политикой QA для нашего проекта: не более 10 цикломатическая сложность за функцию.

Значение: не более 10 'if', 'else', 'try', 'catch' и другой оператор ветвления потока кода. Правильно. Как я объяснил в « Вы тестируете закрытый метод? », такая политика имеет много хороших побочных эффектов.

Но: в начале нашего проекта (200 человек - 7 лет) мы счастливо регистрировались (и нет, мы не можем легко делегировать это какому-то «1013 * Аспектно-ориентированному программированию »). подход для бревен).

myLogger.info("A String");
myLogger.fine("A more complicated String");
...

И когда появились первые версии нашей Системы, у нас возникла огромная проблема с памятью не из-за ведения журнала (которое в какой-то момент было отключено), а из-за параметров log (строки) , которые всегда вычисляются, затем передаются в функции 'info ()' или 'fine ()' только для того, чтобы обнаружить, что уровень ведения журнала был «ВЫКЛ» и что регистрация не выполнялась!

Итак, QA вернулась и призвала наших программистов вести условную регистрацию. Всегда.

if(myLogger.isLoggable(Level.INFO) { myLogger.info("A String");
if(myLogger.isLoggable(Level.FINE) { myLogger.fine("A more complicated String");
...

Но теперь, с этим 10 цикломатическим уровнем сложности «не может быть перемещен» на предел функции, они утверждают, что различные журналы, которые они помещают в свою функцию, воспринимаются как бремя, потому что каждый «if (isLoggable ()» ) "считается +1 цикломатической сложностью!

Таким образом, если у функции есть 8 'if', 'else' и т. Д. В одном тесно связанном алгоритме, который трудно разделить, и 3 критических действия журнала ... они нарушают предел, даже если условные журналы могут не быть действительно частью упомянутой сложности этой функции ...

Как бы вы решили эту ситуацию?
Я видел пару интересных эволюций кодирования (из-за этого «конфликта») в моем проекте, но я просто хочу сначала высказать ваши мысли.


Спасибо за все ответы.
Я должен настаивать на том, что проблема связана не с «форматированием», а с «оценкой аргумента» (оценка может быть очень дорогостоящей, только перед вызовом метода, который ничего не будет делать)
Поэтому, когда написано выше «A String», я на самом деле имел в виду aFunction (), с aFunction (), возвращающей String, и являющейся вызовом сложного метода, собирающего и вычисляющего все виды данных журнала, которые должны отображаться регистратором ... или нет (отсюда проблема и обязательство использовать условное ведение журнала, отсюда и актуальная проблема искусственного увеличения «цикломатической сложности» ...)

Теперь я получаю точку ' variadic function', предложенную некоторыми из вас (спасибо, Джон).
Примечание: быстрый тест в java6 показывает, что моя функция varargs оценивает свои аргументы перед вызовом, поэтому она не может быть применена для вызова функции, но для «Объекта извлечения журнала» (или «обертки функции») , для которого toString () будет вызываться только при необходимости. Понял.

Я уже опубликовал свой опыт по этой теме.
Я оставлю его там до следующего вторника для голосования, а затем выберу один из ваших ответов.
Еще раз спасибо за все предложения :) 1050 *

Ответы [ 12 ]

1 голос
/ 16 сентября 2009

Вот элегантное решение с использованием троичного выражения

logger.info (logger.isInfoEnabled ()? «Оператор журнала идет сюда ...»: null);

1 голос
/ 20 сентября 2008

Как бы я ни ненавидел макросы в C / C ++, на работе у нас есть #defines для части if, которая в случае false игнорирует (не оценивает) следующие выражения, но если true возвращает поток, в который можно передать данные используя оператор <<. Как это: </p>

LOGGER(LEVEL_INFO) << "A String";

Я предполагаю, что это устранит дополнительную «сложность», которую видит ваш инструмент, а также устранит любые вычисления строки или любые выражения, которые будут записываться в журнал, если уровень не был достигнут.

...