Упражнение 25 из раздела «Несвязанность и закон Деметера»
Ответ: Переменная acct передается в виде параметра, так что вызов getBalance является допустимым. Вызов amt.printFormat() таковым не является. Мы не «владеем» amt, и он не был передан нам. Мы могли устранить связывание showBalance с Money при помощи вставки, подобной представленной ниже:
void showBalance(BankAccount b) {
b.printBalance();
}
Упражнение 26 из раздела «Несвязанность и закон Деметера»
Ответ: Поскольку класс Colada создает и владеет myBlender и myStuff, то обращения к addlngredients и elements являются допустимыми.
Упражнение 27 из раздела «Несвязанность и закон Деметера»
Ответ: В этом случае processTransaction владеет amt – он создается на стеке. Происходит передача acct, поэтому допустимыми являются как setValue, так и setBalance. Но processTransaction не владеет who, поэтому вызов who->name() является нарушением. Закон Деметера предлагает заменить эту строку на следующую:
markWorkflow(acct.name (), SET_BALANCE);
Программе в processTransaction не придется узнавать, какой дочерний объект в пределах BankAccount носит это имя – эта информация о структуре не должна разглашаться через контракт BankAccount. Вместо этого мы запрашиваем у BankAccount имя на счете. Он знает, где хранится имя (может быть, в объекте Person, в объекте Business, или в полиморфном объекте Customer).
Упражнение 28 из раздела «Метапрограммирование»
Ответ: Здесь не приводятся категорические ответы – вопросы предназначались в основном для того, чтобы дать вам пищу для размышлений. И вот что мы думаем:
1. Назначения коммуникационного порта. Ясно, что эта информация должна сохраняться в виде метаданных. Но на каком уровне детализации? Некоторые коммуникационные программы системы Windows позволяют выбирать только скорость в бодах и порт (скажем, СОМ1 – COM4). Но вероятно вам придется указать размер слова, четность, стоповые биты, и настройку дуплексной связи. Старайтесь допускать самый мелкий уровень детализации, там где это разумно с практической точки зрения.
2. Поддержка выделения синтаксических конструкций различных языков в программе редактирования. Она должна быть реализована в виде метаданных. Вы же не хотите, чтобы вам пришлось переделывать программу только потому, что в последней версии языка Java было введено новое ключевое слово.
3. Поддержка редактора для различных графических устройств. Эту поддержку было бы трудно реализовать исключительно в виде метаданных. Вам не хотелось бы нагружать приложение многими драйверами устройств только для того, чтобы выбрать один из них во время выполнения программы. Однако вы могли воспользоваться метаданными для указания имени драйвера и динамической загрузки программы. Это еще один аргумент для сохранении метаданных в удобочитаемом формате; если вы используете программу для установки дисфункционального видеодрайвера, то вы не сможете переустановить его, пользуясь этой программой.
4. Конечный автомат для программы синтаксического анализа или сканера.
Это зависит от того, анализируете вы или просматриваете. Если анализируете некоторые данные, которые жестко определены в стандартах и скорее всего не будут изменены без одобрения конгресса США, то жесткое кодирование вполне годится. Но если вы сталкиваетесь с более изменчивой ситуацией, то может быть, более выгодным является внешнее определение таблиц состояний.
5. Типовые значения и результаты, используемые в модульном тестировании.
Большинство приложений определяет эти значения как встроенные в тестовый стенд, но вы можете добиться большей гибкости, перемещая тестовые данные и определение приемлемых результатов за пределы самой программы.
Упражнение 29 из раздела «Всего лишь представление»
Ответ: В программу Flight мы добавим ряд дополнительных методов душ поддержания двух списков «слушателей»: для уведомления о листе ожидания и о полной загрузке рейса.
public interface Passenger {
public void waitListAvailable();
}
public interface Flight {
...
public void addWaitListListener(Passenger p);
public void removeWaitUstUstener(Passenger p);
public void addFullListener(FullListener b);
public void removeFullListener(FullListener b);
...
}
public interface BigReport extends FullListener {
public void FlightFullAlert(Flight f);
}
При неудачной попытке добавить Passenger, поскольку рейс полностью забронирован, мы можем (как вариант) поместить Passenger в лист ожидания. При открытии вакансии производится вызов метода waitListAvailable. Затем этот метод может осуществить выбор: либо добавить Passenger автоматически, либо дать указание сотруднику авиакомпании позвонить заказчику и выяснить, заинтересован ли он еще в рейсе, и т. п. Теперь мы обладаем достаточной гибкостью, чтобы избрать линию поведения, исходя из пожеланий клиента.
Читать дальше