или
>deliverPay(Employee e, Money pay)
и так далее. Все эти функции будут иметь все ту же ущербную структуру.
Решение проблемы (листинг 3.5) заключается в том, чтобы похоронить команду switch в фундаменте АБСТРАКТНОЙ ФАБРИКИ [GOF] и никому ее не показывать. Фабрика использует команду switch для создания соответствующих экземпляров потомков Employee, а вызовы функций calculatePay, isPayDay, deliverPay и т.д. проходят полиморфную передачу через интерфейс Employee.
Листинг 3.5. Employee и Factory
>public abstract class Employee {
> public abstract boolean isPayday();
> public abstract Money calculatePay();
> public abstract void deliverPay(Money pay);
>}
>-----------------
>public interface EmployeeFactory {
> public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
>}
>-----------------
>public class EmployeeFactoryImpl implements EmployeeFactory {
> public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
> switch (r.type) {
> case COMMISSIONED:
> return new CommissionedEmployee(r) ;
> case HOURLY:
> return new HourlyEmployee(r);
> case SALARIED:
> return new SalariedEmploye(r);
> default:
> throw new InvalidEmployeeType(r.type);
> }
> }
>}
Мое общее правило в отношении команд switch гласит, что эти команды допустимы, если они встречаются в программе однократно, используются для создания полиморфных объектов и скрываются за отношениями наследования, чтобы оставаться невидимыми для остальных частей системы [G23]. Конечно, правил без исключений не бывает и в некоторых ситуациях приходится нарушать одно или несколько условий этого правила.
Используйте содержательные имена
В листинге 3.7 я переименовал нашу функцию testableHtml в SetupTeardownIncluder.render. Новое имя гораздо лучше, потому что оно точнее описывает, что делает функция. Кроме того, всем приватным методам были присвоены столь же содержательные имена isTestable, includeSetupAndTeardownPages и т.д. Трудно переоценить пользу хороших имен. Вспомните принцип Уорда: «Вы работаете с чистым кодом, если каждая функция в основном делает то, что вы от нее ожидали». Половина усилий по реализации этого принципа сводится к выбору хороших имен для компактных функций, выполняющих одну операцию. Чем меньше и специализированнее функция, тем проще выбрать для нее содержательное имя.
Не бойтесь использовать длинные имена. Длинное содержательное имя лучше короткого невразумительного. Выберите схему, которая позволяет легко прочитать слова в имени функции, а затем составьте из этих слов имя, которое описывает назначение функции.