Установка Studio Разработки Бизнес-аналитики 2008 года

С текущими платформами журналирования вопрос спорен

, Текущие платформы журналирования как slf4j или log4j 2 не требуют защитных операторов в большинстве случаев. Они используют параметризованный оператор журнала так, чтобы событие могло быть зарегистрировано безусловно, но сообщение, форматирующее только, происходит, если событие включено. Конструкция сообщения выполняется по мере необходимости регистратором, а не преимущественно приложением.

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

защитные операторы, действительно добавляющие сложность?

Рассматривают, исключая вход защитных операторов от цикломатического вычисления сложности.

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

Негибкие метрики могут заставить в других отношениях хорошего программиста стать плохим. Будьте осторожны!

Предположение, что Ваши инструменты для вычисления сложности не могут быть адаптированы в соответствии с тем градусом, следующий подход, может предложить обходное решение.

потребность в условном выражении, регистрирующемся

, я предполагаю, что Ваши защитные операторы были представлены, потому что у Вас был код как это:

private static final Logger log = Logger.getLogger(MyClass.class);

Connection connect(Widget w, Dongle d, Dongle alt) 
  throws ConnectionException
{
  log.debug("Attempting connection of dongle " + d + " to widget " + w);
  Connection c;
  try {
    c = w.connect(d);
  } catch(ConnectionException ex) {
    log.warn("Connection failed; attempting alternate dongle " + d, ex);
    c = w.connect(alt);
  }
  log.debug("Connection succeeded: " + c);
  return c;
}

В Java, каждый из операторов журнала создает новое StringBuilder и вызывает toString() метод на каждом объекте, связанном к строке. Эти toString() методы, в свою очередь, вероятно, создадут StringBuilder собственные экземпляры, и вызовут toString() методы их участников, и так далее, через график потенциально большого объекта. (Прежде чем Java 5, это было еще более дорого, с тех пор StringBuffer использовался, и все его операции синхронизируются.)

Это может быть относительно дорогостоящим, особенно если оператор журнала находится в некотором выполняемом в большой степени пути выполнения кода. И, записанный как выше, что дорогое форматирование сообщения происходит, даже если регистратор обязан отбросить результат, потому что уровень журнала слишком высок.

Это приводит к введению защитных операторов формы:

  if (log.isDebugEnabled())
    log.debug("Attempting connection of dongle " + d + " to widget " + w);

С этой защитой, оценкой аргументов d и w и конкатенация строк выполняется только при необходимости.

решение для А для простого, эффективного входа

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

public final class FormatLogger
{

  private final Logger log;

  public FormatLogger(Logger log)
  {
    this.log = log;
  }

  public void debug(String formatter, Object... args)
  {
    log(Level.DEBUG, formatter, args);
  }

  … &c. for info, warn; also add overloads to log an exception …

  public void log(Level level, String formatter, Object... args)
  {
    if (log.isEnabled(level)) {
      /* 
       * Only now is the message constructed, and each "arg"
       * evaluated by having its toString() method invoked.
       */
      log.log(level, String.format(formatter, args));
    }
  }

}

class MyClass 
{

  private static final FormatLogger log = 
     new FormatLogger(Logger.getLogger(MyClass.class));

  Connection connect(Widget w, Dongle d, Dongle alt) 
    throws ConnectionException
  {
    log.debug("Attempting connection of dongle %s to widget %s.", d, w);
    Connection c;
    try {
      c = w.connect(d);
    } catch(ConnectionException ex) {
      log.warn("Connection failed; attempting alternate dongle %s.", d);
      c = w.connect(alt);
    }
    log.debug("Connection succeeded: %s", c);
    return c;
  }

}

Теперь, ни одно из расположения каскадом toString() вызовы с их распределениями буферов произойдут , если они не будут необходимы! Это эффективно устраняет хит производительности, который привел к защитным операторам. Один маленький штраф, в Java, автоупаковал бы любых аргументов типа примитива, которые Вы передаете регистратору.

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

Дальнейшие улучшения

Также примечание, что в Java MessageFormat объект мог использоваться вместо "формата" String, который дает Вам дополнительные возможности, такие как формат выбора для обработки кардинальных чисел более аккуратно. Другая альтернатива должна была бы реализовать Вашу собственную возможность форматирования, которая вызывает некоторый интерфейс, который Вы определяете для "оценки", а не основного toString() метод.

13
задан Tracy Barker 19 November 2009 в 16:56
поделиться