Если один модуль зависит от другого, зависимость должна быть не только логической, но и физической. Зависимый модуль не должен делать никаких предположений (иначе говоря, создавать логические зависимости) относительно того модуля, от которого он зависит. Вместо этого он должен явно запросить у этого модуля всю необходимую информацию.
Допустим, вы пишете функцию, которая выводит текстовый отчет об отработанном времени. Класс с именем HourlyReporter собирает все данные в удобной форме и передает их классу HourlyReportFormatter для вывода (листинг 17.1).
public class HourlyReporter {
private HourlyReportFormatter formatter;
private List
private final int PAGE_SIZE = 55;
public HourlyReporter(HourlyReportFormatter formatter) {
this.formatter = formatter;
page = new ArrayList
}
public void generateReport(List
for (HourlyEmployee e : employees) {
addLineItemToPage(e);
if (page.size() == PAGE_SIZE)
printAndClearItemList();
}
if (page.size() > 0)
printAndClearItemList();
}
private void printAndClearItemList() {
formatter.format(page);
page.clear();
}
private void addLineItemToPage(HourlyEmployee e) {
LineItem item = new LineItem();
item.name = e.getName();
item.hours = e.getTenthsWorked() / 10;
item.tenths = e.getTenthsWorked() % 10;
page.add(item);
}
public class LineItem {
public String name;
public int hours;
public int tenths;
}
}
У этого кода имеется логическая зависимость, лишенная физического воплощения. Удастся ли вам найти ее? Речь идет о константе PAGE_SIZE. Почему класс HourlyReporter должен знать размер страницы? За размер страницы должен отвечать класс HourlyReportFormatter.
Факт объявления PAGE_SIZE в HourlyReporter указывает на неверное размещение [G17]. Разработчик полагает, что классу HourlyReporter необходимо знать размер страницы. Такое предположение является логической зависимостью. Работа HourlyReporter зависит от того факта, что HourlyReportFormatter поддерживает размер страницы до 55. Если какая-то реализация HourlyReportFormatter не сможет работать с такими страницами, произойдет ошибка.
Чтобы создать физическое представление этой зависимости, мы можем включить в HourlyReportFormatter новый метод с именем getMaxPageSize(). В дальнейшем HourlyReporter вызывает эту функцию вместо того, чтобы использовать константу PAGE_SIZE.
G23: Используйте полиморфизм вместо if/Else или switch/Case
Эта рекомендация может показаться странной, если вспомнить главу 6. Ведь в этой главе говорилось, что в тех частях системы, в которые с большей вероятностью будут добавляться новые функции, а не новые типы, команды switch вполне уместны.
Во-первых, команды switch чаще всего используются только потому, что они представляют очевидное решение методом «грубой силы», а не самое уместное решение для конкретной ситуации. Таким образом, это эвристическое правило напоминает нам о том, что до применения switch следует рассмотреть возможность применения полиморфизма.
Во-вторых, ситуации, в которых состав функций менее стабилен, чем состав типов, встречаются относительно редко. Следовательно, к каждой конструкции switch следует относиться с подозрением.
Я использую правило «ОДНОЙ КОМАНДЫ SWITCH»:
G24: Соблюдайте стандартные конвенции
Все рабочие группы должны соблюдать единые стандарты кодирования, основанные на отраслевых нормах. Стандарт кодирования определяет, где объявляются переменные экземпляров; как присваиваются имена классов, методов и переменных; где размещаются фигурные скобки и т.д. Документ с явным описанием этих правил не нужен — сам код служит примером оформления.
Правила должны соблюдаться всеми участниками группы. Это означает, что каждый участник группы должен быть достаточно разумным, чтобы понимать: неважно, как именно размещаются фигурные скобки, если только все согласились размещать их одинаковым образом.