Сейчас я читаю во второй раз замечательную книгу Чистый код Роберта С. Мартина, также известного как дядя Боб, и я думаю, что это хорошая идея записать наиболее важные идеи, которые он пытается донести до нас. Сегодня я сосредоточусь на третьей главе.
Используйте описательные имена
Не бойтесь делать имя длинным. Длинное описательное имя лучше, чем короткое загадочное имя. Длинное описательное имя лучше длинного описательного комментария. Используйте соглашение об именах, которое позволяет легко читать несколько слов в именах функций, а затем используйте эти несколько слов, чтобы дать функции имя, которое говорит о том, что она делает.
Будьте последовательны в своих именах. Используйте те же фразы, существительные и глаголы в именах функций, которые вы выбираете для своих модулей.
Аргументы функции
Идеальное количество аргументов для функции – ноль (ниладический). Далее идет один (монадический), за ним следует два (диадический). По возможности следует избегать трехаргументов (троичных). Более трех требует особого обоснования и в любом случае не будет использоваться.
Аргументы еще сложнее с точки зрения тестирования. Представьте себе сложность написания всех тестовых случаев, чтобы убедиться, что все различные комбинации аргументов работают правильно. Если нет аргументов, это тривиально. Если есть один аргумент, если не слишком сложно. С двумя аргументами проблема становится немного сложнее. При наличии более двух аргументов проверка каждой комбинации подходящих значений может оказаться сложной задачей.
Общие монадические формы
Есть две очень распространенные причины для передачи одного аргумента в функцию. Вы можете задавать вопрос об этом аргументе, как в boolean exists(String file), или вы оперируете этим аргументом, преобразовывая его во что-то другое и возвращая его.
public String transform(String text);
этот способ лучше, чем:
public void transform(String text);
Использование выходного аргумента вместо возвращаемого значения для преобразования сбивает с толку. Если функция собирается преобразовать свой входной аргумент, преобразование должно отображаться как возвращаемое значение. Действительно, return String лучше, чем void, даже если реализация в первом случае просто возвращает входной аргумент. По крайней мере, он все еще следует форме трансформации.
Аргументы флага
Аргументы флага уродливы. Передача логического значения в функцию — поистине ужасная практика. Это сразу усложняет сигнатуру метода, громко заявляя, что эта функция делает не одну вещь. Он делает одно, если флаг истинный, и другое, если флаг ложный.
Объекты аргумента
Когда кажется, что функции требуется более двух или трех аргументов, вполне вероятно, что некоторые из этих аргументов должны быть заключены в отдельный класс.
Не имеют побочных эффектов
Есть побочные эффекты ложь. Ваша функция обещает сделать одно, но делает и другие скрытые вещи. Иногда он будет вносить неожиданные изменения в переменные своего собственного класса. Иногда это приведет к параметрам, переданным в функцию, или к системным глобальным переменным. В любом случае это коварные и вредные заблуждения, которые часто приводят к странным временным связям и зависимостям порядка.
public boolean checkPassword(String userName, String password);
В этом случае эта функция «checkPassword» не просто проверяет этот пароль, если нет, регистрирует пользователя, если эти учетные данные действительны.
Если у вас должна быть временная связь, вы должны ясно указать это в названии функции, хотя это, безусловно, нарушает принцип «делать одно дело».
public boolean checkPasswordAndInitializeSession(String userName, String password);
Выводы
Джикстрасказал, что каждая функция и каждая книга внутри функции должны иметь один вход и один выход. Соблюдение этих правил означает, что в функции должен быть только один оператор return, оператор break или continue в цикле и никогда не должен быть оператор goto.
Таким образом, если вы сохраняете свои функции небольшими, то несколько операторов returns, break или continue не причинят вреда и иногда могут быть даже более выразительными, чем правило одного входа, одного выхода. С другой стороны, goto имеет смысл только в больших функциях, поэтому его следует избегать.