Чистый код. Создание, анализ и рефакторинг (Мартин) - страница 67


Листинг 5.3

>public class ReporterConfig {


>  /**

>   * Имя класса слушателя

>   */

>  private String m_className;

>  /**

>   * Свойства слушателя

>   */

>  private List m_properties = new ArrayList();


>  public void addProperty(Property property) {

>    m_properties.add(property);

>  }

Листинг 5.4 читается гораздо проще. Он нормально воспринимается «с одного взгляда» — по крайней мере, для меня. Я смотрю на него и сразу вижу, что передо мной класс с двумя переменными и одним методом; для этого мне не приходится вертеть головой или бегать по строчкам глазами. В предыдущем листинге для достижения того же уровня понимания приходится потрудиться намного больше.


Листинг 5.4

>public class ReporterConfig {

>  private String m_className;

>  private List m_properties = new ArrayList();


>  public void addProperty(Property property) {

>    m_properties.add(property);

>  }

Вертикальные расстояния

Вам когда-нибудь доводилось метаться по классу, прыгая от одной функции к другой, прокручивая исходный файл вверх-вниз, пытаясь разобраться, как функции связаны друг с другом и как они работают, — только для того, чтобы окончательно заблудиться в его запутанных нагромождениях? Когда-нибудь искали определение функции или переменной по цепочкам наследования? Все это крайне неприятно, потому что вы стараетесь понять, как работает система, а вместо этого вам приходится тратить время и интеллектуальные усилия на поиски и запоминание местонахождения отдельных фрагментов.

Концепции, тесно связанные друг с другом, должны находиться поблизости друг от друга по вертикали [G10]. Разумеется, это правило не работает для концепций, находящихся в разных файлах. Но тесно связанные концепции и не должны находиться в разных файлах, если только это не объясняется очень вескими доводами. Кстати, это одна из причин, по которой следует избегать защищенных переменных.

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

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

>private static void readPreferences() {

>  InputStream is= null;

>  try {

>    is= new FileInputStream(getPreferencesFile());

>    setPreferences(new Properties(getPreferences()));