2.10. Зависимости между методами
Если несколько методов используют одни и те же глобально доступные изменяемые данные (поля), это может грозить довольно ощутимыми проблемами, самой грозной из которых является необходимость вызывать методы в строго определенном порядке.
Пусть в классе есть следующие методы:
- fill(): записывает данные во внутренний массив;
- sort(): сортирует внутренний массив;
- max(): возвращает максимальный элемент этого массива.
Предположим, что метод max() в реализации использует то, что массив отсортирован, т.е. возвращает последний элемент массива.
Метод max() предполагает, что метод sort() вызывался после последнего вызова fill(). Если клиент не вызвал sort(), метод max будет работать неправильно.
В этой ситуации возникновение ошибки очень вероятно, но возможны случаи, когда ошибка не будет замечена — если максимальный элемент случайно окажется в конце массива. Ошибка становится трудно воспроизводимой.
Стоит создавать методы так, чтобы они не зависели друг от друга, то есть чтобы любой метод можно было вызвать в любой момент. Однако такое не всегда возможно.
В этом случае нужно либо гарантировать, что метод max() вызовет sort(), если тот не был вызван, либо гарантировать, что sort() вызывается в конце метода fill(), либо проверять в методе max(), что sort() не вызывался и бросать исключение. Последний путь — наименее приятный.
Методы должны «общаться» между собой, передавая друг другу параметры. Если методы и используют значения полей, это должно быть четко продиктовано той абстракцией, которую реализует класс.
Самые хорошие методы не имеют побочных эффектов (в C++ они помечаются модификатором const) — они не меняют состояния объектов и безопасны для своего окружения. Однако обойтись только такими методами удается далеко не всегда.