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

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

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

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

Распределенные системы создают дополнительный уровень сложности. Вы должны решить, как действовать в случае отказа внешних зависимостей. Если система сильно распределена, это может происходить часто. Учтите это обстоятельство при выборе политики ведения журнала.

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

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

<p>WET размазывает узкие места производительности</p><p>Кирк Пеппердин</p>

Значимость принципа DRY (Don’t Repeat Yourself — не повторяйся) состоит в том, что он формализует следующую идею: каждый элемент знаний в системе должен иметь единственное представление. Иными словами, знание должно ограничиваться единственной реализацией. Полную противоположность DRY представляет WET (Write Every Time — пиши каждый раз). Наш код можно назвать «сырым» (WET), когда знание представлено в коде одновременно несколькими способами. Скрытое влияние DRY и WET на производительность становится понятным после рассмотрения их многочисленных эффектов на конкретном примере.

Рассмотрим некоторую функциональность нашей системы (назовем ее X), являющуюся узким местом для процессора. Допустим, что функция X потребляет 30 % мощности процессора. Теперь предположим, что у функции X есть 10 различных реализаций. В среднем каждая реализация потребляет 3 % процессорного времени. Поскольку такой уровень использования процессора не вызывает беспокойства, при беглом анализе можно не заметить, что эта функция создает узкое место. Но допустим, что мы каким-то образом выяснили, что функция X — узкое место. Тогда ставится задача найти и исправить каждую реализацию. Для WET у нас есть 10 разных реализаций, которые нужно найти и исправить. В случае DRY мы сразу увидим загрузку процессора в 30 %, а размер кода для исправления будет в 10 раз меньше. К тому же не потребуется выискивать все многочисленные реализации.

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

public class UsageExample {

   private ArrayList allCustomers = new ArrayList();

   //…

   public ArrayList findCustomersThatSpendAtLeast(Money amount) {

     ArrayList customersOfInterest = new ArrayList();

     for (Customer customer: allCustomers) {

       if (customer.spendsAtLeast(amount))

         customersOfInterest.add(customer);

     }

     return customersOfInterest;

 }

}

Перейти на страницу:

Все книги серии Профессионально

Похожие книги