>}
Если работник предъявил счет по затратам на питание, то сумма включается в общий итог. Если счет отсутствует, то работнику за этот день начисляется определенная сумма. Исключение загромождает логику программы. А если бы удалось обойтись без обработки особого случая? Это позволило бы заметно упростить код:
>MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
>m_total += expenses.getTotal();
Можно ли упростить код до такой формы? Оказывается, можно. Мы можем изменить класс ExpenseReportDAO, чтобы он всегда возвращал объект MealExpense. При отсутствии предъявленного счета возвращается объект MealExpense, у которого в качестве затрат указана стандартная сумма, начисляемая за день:
>public class PerDiemMealExpenses implements MealExpenses {
> public int getTotal() {
> // Вернуть стандартные ежедневные затраты на питание
> }
>}
Такое решение представляет собой реализацию паттерна ОСОБЫЙ СЛУЧАЙ [Fowler]. Программист создает класс или настраивает объект так, чтобы он обрабатывал особый случай за него. Это позволяет избежать обработки исключительного поведения в клиентском коде. Все необходимое поведение инкапсулируется в объекте особого случая.
На мой взгляд, при любых обсуждениях обработки ошибок необходимо упомянуть о неправильных действиях программистов, провоцирующих ошибки. На первом месте в этом списке стоит возвращение null. Я видел бесчисленное множество приложений, в которых едва ли не каждая строка начиналась с проверки null. Характерный пример:
>public void registerItem(Item item) {
> if (item != null) {
> ItemRegistry registry = persistentStore.getItemRegistry();
> if (registry != null) {
> Item existing = registry.getItem(item.getID());
> if (existing.getBillingPeriod().hasRetailOwner()) {
> existing.register(item);
> }
> }
> }
>}
Если ваша кодовая база содержит подобный код, возможно, вы не видите в нем ничего плохого, но это не так! Возвращая null, мы фактически создаем для себя лишнюю работу, а для вызывающей стороны — лишние проблемы. Стоит пропустить всего одну проверку null, и приложение «уходит в штопор».
А вы заметили, что во второй строке вложенной команды if проверка null отсутствует? Что произойдет во время выполнения, если значение persistentStore окажется равным null? Произойдет исключение NullPointerException; либо кто-то перехватит его на верхнем уровне, либо не перехватит. В обоих случаях все будет плохо. Как реагировать на исключение NullPointerException, возникшее где-то в глубинах вашего приложения?