Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы на экзаменационные вопросы по ЭСТП.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
399.63 Кб
Скачать

12. Закон Деметры. Опасность построения гибридов объектов и структур данных. Объекты передачи данных и активные записи

ЗАКОН ДЕМЕТРЫ

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

ГИБРИДЫ

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

Подобные гибриды усложняют как добавление новых функций, так и новых структур данных. Они объединяют все худшее из обеих категорий.

13. Обработка ошибок. Исключения и коды ошибок. Использование паттерна «Особый случай».

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

ИСПОЛЬЗУЙТЕ ИСКЛЮЧЕНИЯ ВМЕСТО КОДОВ ОШИБОК

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

НАЧНИТЕ С НАПИСАНИЯ КОМАНДЫ TRY-CATCH-FINALLY

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

Блоки try в каком-то отношении напоминают транзакции. Секция catch должна оставить программу в целостном состоянии, что бы и произошло в секции try. По этой причине написание кода, который может инициировать исключения, рекомендуется начинать с конструкции try-catch-final 1у. Это поможет вам определить, чего должен ожидать пользователь кода, что бы ни произошло в коде try.

ОПРЕДЕЛИТЕ НОРМАЛЬНЫЙ ПУТЬ ВЫПОЛНЕНИЯ

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

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

try {

MealExpenses expenses = expenseReportDAO.getMeals(employee.getIDO);

m_total += expenses.getTotalО:

} catch(MealExpensesNotFound e) {

m_total += getMealPerDiemO:

}

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

MealExpenses expenses = expenseReportDAO.getMeals(employee.getlDO);

m_total += expenses, get Total О;

Можно ли упростить код до такой формы? Оказывается, можно. Мы можем изменить класс ExpenseReportDAO, чтобы он всегда возвращал объект Meal Expense. При отсутствии предъявленного счета возвращается объект Meal Expense, у которого в качестве затрат указана стандартная сумма, начисляемая за день:

public class PerDiemMealExpenses implements MealExpenses {

public int getTotalО {

// Вернуть стандартные ежедневные затраты на питание

}}

Такое решение представляет собой реализацию паттерна ОСОБЫЙ СЛУЧАЙ [Fowler]. Программист создает класс или настраивает объект так, чтобы он обрабатывал особый случай за него. Это позволяет избежать обработки исключительного поведения в клиентском коде. Все необходимое поведение инкапсулируется в объекте особого случая.