Стиль кода Java AOSP для участников

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

Быть последовательным

Одно из простейших правил - БУДЬТЕ ПОСТОЯННЫМ. Если вы редактируете код, уделите несколько минут, чтобы посмотреть на окружающий код и определить его стиль. Если этот код использует пробелы вокруг , if пунктов, вы должны тоже. Если в комментариях к коду есть маленькие прямоугольники со звездочками, сделайте так, чтобы вокруг них тоже были маленькие прямоугольники со звездочками.

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

Правила языка Java

Android следует стандартным соглашениям о кодировании Java с дополнительными правилами, описанными ниже.

Не игнорируйте исключения

Может возникнуть соблазн написать код, игнорирующий исключение, например:

  void setServerPort(String value) {
      try {
          serverPort = Integer.parseInt(value);
      } catch (NumberFormatException e) { }
  }

Не делай этого. Хотя вы можете подумать, что ваш код никогда не столкнется с этим условием ошибки или что его не важно обрабатывать, игнорирование этого типа исключения создает в вашем коде мины, которые когда-нибудь может сработать кто-то другой. Вы должны принципиально обрабатывать каждое исключение в вашем коде; конкретное обращение варьируется в зависимости от случая.

" В любое время кто - то пустой пункт поймать , они должны иметь жуткое чувство. Есть определенные случаи , когда на самом деле правильно , что нужно сделать, но , по крайней мере , вы должны думать об этом. В Java вы не можете избежать жуткое чувство. "- Джеймс Гослинг

Приемлемые альтернативы (в порядке предпочтения):

  • Передайте исключение вызывающей стороне вашего метода.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • Создайте новое исключение, соответствующее вашему уровню абстракции.
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • Ручка ошибки корректно и заменить соответствующее значение в catch {} блока.
      /** Set port. If value is not a valid number, 80 is substituted. */
    
      void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            serverPort = 80;  // default port for server
        }
      }
    
  • Поймать исключение и бросить новый экземпляр RuntimeException . Это опасно, поэтому делайте это только в том случае, если вы уверены, что в случае возникновения этой ошибки правильным решением будет сбой.
      /** Set port. If value is not a valid number, die. */
    
      void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("port " + value " is invalid, ", e);
        }
      }
    
  • В крайнем случае, если вы уверены, что игнорирование исключения является уместным, вы можете игнорировать его, но вы также должны указать причину с уважительной причиной.
    /** If value is not a valid number, original port number is used. */
    
    void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            // Method is documented to just ignore invalid user input.
            // serverPort will just be unchanged.
        }
    }
    

Не ловите общие исключения

Может возникнуть соблазн полениться при отлове исключений и сделать что-то вроде этого:

  try {
      someComplicatedIOFunction();        // may throw IOException
      someComplicatedParsingFunction();   // may throw ParsingException
      someComplicatedSecurityFunction();  // may throw SecurityException
      // phew, made it all the way
  } catch (Exception e) {                 // I'll just catch all exceptions
      handleError();                      // with one generic handler!
  }

Не делай этого. Почти во всех случаях, это нецелесообразно , чтобы поймать родовое Exception или Throwable (предпочтительно не Throwable , потому что она включает в себя Error исключения). Это опасно , потому что это означает , что исключения вы никогда не ожидали (включая исключение во время выполнения , как ClassCastException ) увязнуть в обработке ошибок на уровне приложения. Он скрывает свойства обработки ошибок вашего кода, то есть, если кто-то добавит новый тип исключения в код, который вы вызываете, компилятор не укажет, что вам нужно обрабатывать ошибку по-другому. В большинстве случаев вы не должны одинаково обрабатывать разные типы исключений.

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

Альтернативы перехвату общих исключений:

  • Поймать каждое исключение отдельно как часть мульти-блок улова в, например:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • Реорганизуйте код, чтобы обеспечить более детальную обработку ошибок с несколькими блоками try. Отделите ввод-вывод от синтаксического анализа и обрабатывайте ошибки отдельно в каждом случае.
  • Восстановить исключение. Во многих случаях вам все равно не нужно перехватывать исключение на этом уровне, просто позвольте методу выбросить его.

Помните, что исключения - ваш друг! Когда компилятор жалуется, что вы не поймаете исключение, не сердитесь. Улыбка! Компилятор просто упростил вам поиск проблем во время выполнения в вашем коде.

Не используйте финализаторы

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

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

Полностью квалифицированный импорт

Если вы хотите использовать класс Bar из пакета foo , есть два возможных способа импортировать его:

  • import foo.*;

    Потенциально сокращает количество операторов импорта.

  • import foo.Bar;

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

Использование import foo.Bar; для импорта всего кода Android. Явное исключение делается для Java стандартных библиотек ( java.util.* , java.io.* и т.д.) и модульного тестирования кода ( junit.framework.* ).

Правила библиотеки Java

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

Правила стиля Java

Используйте стандартные комментарии Javadoc

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

/*
 * Copyright 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.foo;

import android.os.Blah;
import android.view.Yada;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Does X and Y and provides an abstraction for Z.
 */

public class Foo {
    ...
}

Каждый класс и нетривиальным публичный метод , который вы напишете должен содержать Javadoc комментарий, по крайней мере одно предложение с описанием того, что делает класс или метод. Это предложение должно начинаться с описательного глагола от третьего лица.

Примеры

/** Returns the correctly rounded positive square root of a double value. */

static double sqrt(double a) {
    ...
}

или

/**
 * Constructs a new String by converting the specified array of
 * bytes using the platform's default character encoding.
 */
public String(byte[] bytes) {
    ...
}

Вам не нужно писать Javadoc для тривиальных получить и установить методы , такие как setFoo() , если все ваши Javadoc бы сказать «множества Foo». Если метод выполняет что-то более сложное (например, применяет ограничение или имеет важный побочный эффект), вы должны задокументировать это. Если не совсем понятно, что означает свойство «Foo», вам следует задокументировать его.

Javadoc принесет пользу каждому написанному вами методу, общедоступному или иному. Общедоступные методы являются частью API и поэтому требуют документации Javadoc. Android не навязывает стиль , специфичную для написания комментариев Javadoc, но вы должны следовать инструкциям в Как написать Doc Комментарии для Javadoc Tool .

Напишите короткие методы

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

Определите поля в стандартных местах

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

Ограничить область действия переменной

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

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

Исключение составляют операторы try-catch. Если переменная инициализируется возвращаемым значением метода, который генерирует проверенное исключение, она должна быть инициализирована внутри блока try. Если значение должно использоваться за пределами блока try, то оно должно быть объявлено перед блоком try, где оно еще не может быть разумно инициализировано:

// Instantiate class cl, which represents some sort of Set

Set s = null;
try {
    s = (Set) cl.newInstance();
} catch(IllegalAccessException e) {
    throw new IllegalArgumentException(cl + " not accessible");
} catch(InstantiationException e) {
    throw new IllegalArgumentException(cl + " not instantiable");
}

// Exercise the set
s.addAll(Arrays.asList(args));

Однако вы даже можете избежать этого, инкапсулируя блок try-catch в метод:

Set createSet(Class cl) {
    // Instantiate class cl, which represents some sort of Set
    try {
        return (Set) cl.newInstance();
    } catch(IllegalAccessException e) {
        throw new IllegalArgumentException(cl + " not accessible");
    } catch(InstantiationException e) {
        throw new IllegalArgumentException(cl + " not instantiable");
    }
}

...

// Exercise the set
Set s = createSet(cl);
s.addAll(Arrays.asList(args));

Объявите переменные цикла в самом выражении for, если нет веской причины сделать иначе:

for (int i = 0; i < n; i++) {
    doSomething(i);
}

а также

for (Iterator i = c.iterator(); i.hasNext(); ) {
    doSomethingElse(i.next());
}

Выписки по заказу импорта

Порядок операторов импорта следующий:

  1. Импорт Android
  2. Импорт из третьих лиц ( com , junit , net , org )
  3. java и javax

Чтобы точно соответствовать настройкам IDE, импорт должен быть:

  • По алфавиту внутри каждой группы, с заглавными буквами перед строчными буквами (например, Z перед a)
  • Разделенный пустая строка между каждой крупной группировкой ( android , com , junit , net , org , java , javax )

Первоначально требования к стилю для упорядочивания отсутствовали, то есть среды IDE либо всегда меняли порядок, либо разработчикам IDE приходилось отключать функции автоматического управления импортом и вручную поддерживать импорт. Это было сочтено плохим. Когда спросили о стиле Java, предпочтительные стили сильно различались, и дело дошло до Android, которым нужно было просто «выбрать порядок и быть последовательным». Итак, мы выбрали стиль, обновили руководство по стилю и заставили IDE подчиняться ему. Мы ожидаем, что по мере того, как пользователи IDE работают над кодом, импорт во всех пакетах будет соответствовать этому шаблону без дополнительных инженерных усилий.

Мы выбрали этот стиль так, чтобы:

  • Импорт , что люди хотят смотреть на первый , как правило, в верхней части ( android ).
  • Импорт , что люди хотят выглядеть , по крайней мере , как правило, в нижней части ( java ).
  • Люди легко могут следовать этому стилю.
  • IDE могут следовать этому стилю.

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

Используйте пробелы для отступа

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

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

рекомендуемые

Instrument i =
        someLongExpression(that, wouldNotFit, on, one, line);

Не рекомендуется

Instrument i =
    someLongExpression(that, wouldNotFit, on, one, line);

Соблюдайте соглашения об именах полей

  • Непубличный, нестатические имена полей начинаются с m .
  • Статические имена полей начинаются с s .
  • Остальные поля начинаются со строчной буквы.
  • Общедоступные статические конечные поля (константы) являются ALL_CAPS_WITH_UNDERSCORES .

Например:

public class MyClass {
    public static final int SOME_CONSTANT = 42;
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}

Использовать стандартный стиль скобок

Ставьте фигурные скобки в той же строке, что и код перед ними, а не в отдельной строке:

class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

Нам нужны фигурные скобки вокруг операторов условного оператора. Исключение: если все условие (условие и тело) помещается в одну строку, вы можете (но не обязаны) поместить все это в одну строку. Например, это приемлемо:

if (condition) {
    body();
}

и это приемлемо:

if (condition) body();

но это недопустимо:

if (condition)
    body();  // bad!

Ограничить длину линии

Каждая строка текста в вашем коде не должна превышать 100 символов. В то время как много дискуссий вокруг этого вопроса правило, решение остается , что 100 символов максимальная со следующими исключениями:

  • Если строка комментария содержит пример команды или буквальный URL-адрес длиннее 100 символов, эта строка может быть длиннее 100 символов для простоты вырезания и вставки.
  • Строки импорта могут выходить за предел, потому что люди их редко видят (это также упрощает написание инструментов).

Используйте стандартные аннотации Java

Аннотации должны предшествовать другим модификаторам для того же языкового элемента. Простые аннотаций маркеров (например, @Override ) может быть перечислены на ту же строку с элементом языка. Если имеется несколько аннотаций или параметризованных аннотаций, перечислите их по одной в строке в алфавитном порядке.

Стандартные практики Android для трех предопределенных аннотаций в Java:

  • Используйте @Deprecated аннотацию всякий раз , когда использование аннотированных элемента рекомендуется. Если вы используете @Deprecated аннотации, вы должны также иметь @deprecated Javadoc тег , и он должен назвать альтернативную реализацию. Кроме того, помните , что @Deprecated метод еще должен работать. Если вы видите старый код , который имеет @deprecated Javadoc тег, добавьте @Deprecated аннотации.
  • Используйте @Override аннотацию всякий раз , когда метод переопределяет заявление или реализацию из суперкласса. Например, если вы используете @inheritdocs Javadoc тег, и вывести из класса (не интерфейс), вы должны также аннотировать , что метод переопределяет метод родительского класса.
  • Используйте @SuppressWarnings аннотацию только в тех случаях , когда это невозможно устранить предупреждение. Если предупреждение проходит это «невозможно устранить» тест, то @SuppressWarnings аннотации следует использовать, чтобы гарантировать , что все предупреждения отражают актуальные проблемы в коде.

    Когда @SuppressWarnings аннотаций необходимо, оно должно быть с префиксом TODO комментарием , что объясняет «невозможно устранить» состояние. Обычно это идентифицирует класс-нарушитель с неудобным интерфейсом. Например:

    // TODO: The third-party class com.third.useful.Utility.rotate() needs generics
    @SuppressWarnings("generic-cast")
    List<String> blix = Utility.rotate(blax);
    

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

Рассматривайте аббревиатуры как слова

Обращайтесь с акронимами и аббревиатурами как с словами в именах переменных, методов и классов, чтобы сделать имена более удобочитаемыми:

Хороший Плохой
XmlHttpRequest XMLHTTPRequest
getCustomerId getCustomerID
класс Html класс HTML
Строковый URL Строковый URL
длинный идентификатор длинный идентификатор

Поскольку кодовые базы JDK и Android не соответствуют аббревиатурам, практически невозможно согласовать их с окружающим кодом. Поэтому всегда относитесь к аббревиатурам как к словам.

Используйте комментарии TODO

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

// TODO: Remove this code after the UrlTable2 has been checked in.

а также

// TODO: Change this to use a flag instead of a constant.

Если TODO имеет вид «На дату в будущем сделать что - то» , убедитесь , что вы либо включать дату конкретный ( «Фикс к ноябрю 2005 года») или событие конкретной ( «Удалить этот код после того, как все производственные миксеры понимают протокол V7.» ).

Регистрируйтесь экономно

Хотя ведение журнала необходимо, оно отрицательно сказывается на производительности и теряет свою полезность, если оно не будет достаточно кратким. Средства ведения журнала обеспечивают пять различных уровней ведения журнала:

  • ERROR : Используется , когда что - то со смертельным исходом произошел, то есть, что - то будет иметь видимый пользователь последствия и не будет возмещены без удаления некоторых данных, удаления приложений, очистки разделов данных, или перепрошивок всего устройства (или хуже). Этот уровень всегда регистрируется. Проблемы , которые обосновывают некоторые протоколирование на ERROR уровня являются хорошими кандидатами для сообщать сервер статистики сбора.
  • WARNING : Используйте , когда что - то серьезное и неожиданное, то есть то , что будет иметь видимый пользователь последствия , но, скорее всего, будет возмещены без потери данных, выполняя некоторые явные действия, начиная от ожидания или перезагрузки приложения , вплоть до повторного скачивания новая версия приложения или перезагрузка устройства. Этот уровень всегда регистрируется. Проблемы , которые обосновывают лесозаготовки на WARNING уровне также могут быть рассмотрены для представления к серверу статистики сбора.
  • INFORMATIVE : Используйте отметить , что кое - что интересное случилось, что, когда ситуация обнаруживается , что, вероятно, имеет широкое влияние, хотя и не обязательно является ошибкой. Такое условие должно регистрироваться только модулем, который считает, что он является наиболее авторитетным в этом домене (чтобы избежать дублирования журналирования неавторизованными компонентами). Этот уровень всегда регистрируется.
  • DEBUG : Используюсь для дальнейшей записки , что происходит на устройстве , которое может иметь отношение к расследованию и отлаживать неожиданные поведения. Регистрируйте только то, что необходимо для сбора достаточной информации о том, что происходит с вашим компонентом. Если ваши журналы отладки преобладают в журнале, вам следует использовать подробное ведение журнала.

    Этот уровень регистрируется даже на выпуск сборок, и требуется , чтобы быть в окружении , if (LOCAL_LOG) или if LOCAL_LOGD) блок, где LOCAL_LOG[D] определяется в классе или подкомпоненте, так что есть возможность отключить все такое ведение журнала . Таким образом, не должно быть никакого активного логика в if (LOCAL_LOG) блока. Все строки здание для журнала также должно быть помещено внутрь , if (LOCAL_LOG) блок. Не реорганизовать вызов логофф в вызове метода , если он собирается вызвать строку здание , чтобы иметь место за пределами if (LOCAL_LOG) блока.

    Там какой - то код , который до сих пор говорит , что if (localLOGV) . Это тоже считается приемлемым, хотя название нестандартное.

  • VERBOSE : Используйте для всего остального. Этот уровень регистрируется только на отладку сборки и должен быть окружен , if (LOCAL_LOGV) блока (или эквивалент) , так что он может быть составлен из по умолчанию. Любая строка здание удаляется из релиза строит и потребности появляться внутри , if (LOCAL_LOGV) блока.

Примечания

  • В рамках данного модуля, другой , чем на VERBOSE уровне, ошибка следует указывать только один раз , если это возможно. В пределах одной цепочки вызовов функций в модуле только самая внутренняя функция должна возвращать ошибку, а вызывающие абоненты в том же модуле должны добавлять журналы только в том случае, если это существенно помогает изолировать проблему.
  • В цепи модулей, другой , чем на VERBOSE уровне, когда модуль нижнего уровня обнаруживает неверные данные , поступающие из модуля верхнего уровня, модуль нижнего уровня должен войти только эту ситуацию с DEBUG бревна, и только если протоколирование обеспечивает информация, которая иначе недоступна для вызывающего абонента. В частности, нет необходимости регистрировать ситуации, когда возникает исключение (исключение должно содержать всю соответствующую информацию) или когда единственная регистрируемая информация содержится в коде ошибки. Это особенно важно при взаимодействии между каркасом и приложениями, а также условиями , вызванным сторонними приложениями, которые обработаны должным образом в рамках не должен вызывать регистрации выше DEBUG уровня. Единственные ситуации , которые должны привести протоколирование на INFORMATIVE уровни или выше , когда модуль или приложение обнаруживает ошибку на своем уровне или из более низкого уровня.
  • Когда условие, которое обычно оправдывает некоторое ведение журнала, вероятно, произойдет много раз, может быть хорошей идеей реализовать некоторый механизм ограничения скорости, чтобы предотвратить переполнение журналов множеством дублированных копий одной и той же (или очень похожей) информации.
  • Потери подключения к сети считаются обычным явлением, вполне ожидаемы и не должны регистрироваться бесплатно. Потеря подключения к сети , которая имеет последствия в рамках приложения должны быть авторизованы на DEBUG или VERBOSE уровне ( в зависимости от того, являются ли последствия достаточно серьезные и неожиданные достаточно , чтобы быть зарегистрированным в сборке релиз).
  • Наличие полной файловой системы в файловой системе, доступной сторонним приложениям или от их имени, не должно регистрироваться на уровне выше ИНФОРМАЦИОННОГО.
  • Неверные данные , поступающие из любого ненадежного источника (включая любой файл на общем хранилище, или данные , поступающих через сетевое соединение) считается ожидаемым и не должны вызывать какую - либо регистрации на уровне выше , чем DEBUG , когда он обнаружил недействительный (и даже тогда каротаж должно быть как можно более ограниченным).
  • При использовании на String объектов, то + оператор неявно создает StringBuilder экземпляр с размером буфера по умолчанию (16 символов) и потенциально других временных String объектов. Таким образом , явно создавая StringBuilder объекты не дороже , чем полагаться на умолчанию в + оператора (и может быть гораздо более эффективным). Имейте в виду , что код , который вызывает Log.v() компилируется и выполняется на выпуске сборки, в том числе построение строк, даже если журналы не читается.
  • Любое ведение журнала, предназначенное для чтения другими людьми и доступное в сборках релизов, должно быть кратким, но не загадочным, и должно быть понятным. Это включает в себя все лесозаготовки до DEBUG уровня.
  • По возможности продолжайте регистрироваться в одной строке. Допускается длина строки до 80 или 100 символов. По возможности избегайте длины более 130 или 160 символов (включая длину тега).
  • Если вход отчетов успехов, никогда не использовать его на уровне выше , чем VERBOSE .
  • Если вы используете временную регистрацию для диагностики проблемы , что это трудно воспроизвести, сохранить его в DEBUG или VERBOSE уровне и приложить его , если блоки , которые позволяют отключить его во время компиляции.
  • Будьте осторожны с утечками безопасности через журнал. Избегайте регистрации частной информации. В частности, избегайте записи в журнал информации о защищенном содержимом. Это особенно важно при написании кода фреймворка, поскольку заранее не так просто знать, что будет, а что не будет частной информацией или защищенным контентом.
  • Никогда не используйте System.out.println() (или printf() для нативного кода). System.out и System.err попадают в /dev/null , так что ваши операторы печати не имеют видимые эффектов. Однако все построение строки, которое происходит для этих вызовов, по-прежнему выполняется.
  • Золотое правило ведения журнала состоит в том, что ваши журналы не могут без необходимости выталкивать другие журналы из буфера, так же как другие не могут вытеснять ваши.

Правила стиля Javatests

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

testMethod_specificCase1 testMethod_specificCase2

void testIsDistinguishable_protanopia() {
    ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
    assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
    assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}