как и в предыдущей части, мы обсуждали правила выбора имен для переменных, функций, классов и т. д., давайте сделаем еще один шаг к чему-то более важному, а именно: Функции, Функция - это базовый строительный блок и ядро ​​ любой системы.

Но сначала давайте приведем пример, чтобы показать концепции, которые будут обсуждаться. Если у вас внутри стог сена и иголка, и вам нужно вытащить из нее иголку, в каком случае потребуется меньше усилий и времени?

Однозначно, случай номер два будет проще, почему? поскольку он маленький, свернутый и расположенный, что делает иглу кристально чистой.

Разделив стог сена на небольшие упорядоченные части и разделив их на коллекции, каждая коллекция предназначена для определенной цели, что упрощает поиск иголки внутри нее, этот пример вкратце объясняет преимущества разделения и расположения стога сена, он также работает для функции, которые упрощают поиск ошибок и делают код более читаемым и поддерживаемым, давайте погрузимся в эти правила.

Функции должны быть маленькими.

Первое правило функций заключается в том, что они должны быть небольшими, чем меньше функция, тем они четче и удобны для чтения и понимания.

Функции не должны содержать 100 строк. Функции не должны содержать 20 строк.

Блоки и отступы

блоки операторов (if, else, while и for… и т. д.) должны быть одной строкой, эта строка должна быть вызовом функции.

это правило не только помогает сохранить маленькую функцию, но также упрощает чтение и понимание функции, поскольку внутри каждого блока есть только одна строка для вызова функции, имеющей описательное имя, чтобы избежать вложенных блоков, затрудняющих чтение кода.

уровень вложенности внутри функции не должен быть больше одного или двух.

Сделай одно дело

функции должны делать одно. они должны делать это хорошо. только они должны это делать.

Проблема в том, что трудно понять, что такое «одна вещь».

Итак, еще один способ узнать, что функция выполняет больше, чем «одно действие», - это если вы можете извлечь из нее другую функцию с описательным именем, а функции, выполняющие одно действие, нельзя разделить на разделы.

Если вы прочитаете длинную функцию, вы поймете, что там делается больше чем одна вещь. Например, в той же функции вы открываете соединение с БД, выполняете запрос, конвертируете результат в другой тип и обрабатываете особые случаи. Каждое из этих действий должно выполняться в отдельном месте.

Если вам нужно сделать несколько дел, вы должны разделить их на отдельные функции.

«Сложность программного обеспечения возникает из-за того, что одна вещь выполняет две задачи». - Райан Сингер.

Один уровень абстракции для каждой функции

Чтобы убедиться, что наши функции выполняют «одну задачу», нам нужно убедиться, что все операторы внутри нашей функции находятся на одном уровне абстракции.

Чтение кода сверху вниз (правило шага вниз)

Мы хотим, чтобы код читался как повествование сверху вниз. Мы хотим, чтобы за каждой функцией следовали функции следующего уровня абстракции, чтобы мы могли читать программу.

ЗАЯВЛЕНИЯ О ПЕРЕКЛЮЧЕНИИ

Также сложно создать оператор switch, который бы делал что-то одно. По своей природе операторы switch всегда выполняют N вещей.

Его использование нарушает Принцип единой ответственности (SRP), потому что есть несколько причин для его изменения. дополнительный к нарушает Принцип открытости-закрытости (OCP), поскольку он должен изменяться при добавлении новых дел.

Итак, у проблемной функции есть оператор switch:

  1. сделать еще одно.
  2. имеет несколько причин для изменения нарушает SRP.
  3. не открыт для расширенных нарушений OCP.
  4. сложная и длинная функциональная структура.

вы можете решить первые две проблемы, извлекая каждый блок кода кейса для работы и просто возвращая вызов этой функции.

Но класс, в котором есть функция, имеет переключатель внутри, по-прежнему не открыт для расширенного использования, что означает, что каждый раз, когда вам нужно добавить случай, вам нужно изменить этот класс, и чем больше случаев вы добавите, тем длиннее будет функция.

Чтобы решить эту проблему, нам нужно использовать полиморфизм.

полиморфизм

Полиморфизм - это способность объекта принимать различные формы. Простыми словами, вместо использования оператора switch вы будете использовать Полиморфизм, создав суперкласс, у которого есть функция для того, что мы нужно сделать в switch и перезаписать эту функцию в подклассах, например, если оператор switch управляет такими способами оплаты:

double calculatePay(Employee e) {
 switch (e.type) {
 case COMMISSIONED:
 return calculateCommissionedPay(e);
 case HOURLY:
 return calculateHourlyPay(e);
 case SALARIED:
 return calculateSalariedPay(e);
 }
}

вместо этого использовать полиморфизм:

  1. создать интерфейс
public class Payment{
double pay(Employee){
// default case
}
}

2. создайте класс для каждого случая и перезапишите метод оплаты.

public class CommissionedPayment extends Payment{
@overwrite
double pay(Employee e){
}
}
public class HourlyPayment extends Payment{
@overwrite
double pay(Employee e){
}
}
public class SalariedPayment extends Payment{
@overwrite
double pay(Employee e){
}
}

3. используя это

Employee employee = new Employee();
Payment commissionedPayment = new CommissionedPayment();
commissionedPaymen.pay(employee);
Payment hourlyPayment = new HourlyPayment();
hourlyPayment.pay(employee);
Payment salariedPayment = new SalariedPayment();
salariedPayment.pay(employee);

И теперь, если нам нужно добавить еще один метод оплаты, мы просто добавляем еще один класс, чтобы система теперь открыта для расширенного, и для каждого подкласса существует другая реализация метода оплаты, который является использованием: случай для полиморфизма.

Используйте описательные имена

Не бойтесь сделать имя длинным. Длинное описательное имя лучше короткого загадочного. Длинное описательное имя лучше, чем длинный описательный комментарий.

ФУНКЦИОНАЛЬНЫЕ АРГУМЕНТЫ

Категории аргументов функций:

  • Нулевые аргументы (ниладические), идеальное количество аргументов.
  • Один аргумент (монадический).
  • Два аргумента (диадические).
  • Три аргумента (триадный).
  • Не следует использовать более трех (полиадических), не следует использовать без необходимости.

С точки зрения тестирования, большее количество аргументов означает больше усилий для написания тестовых сценариев, чтобы гарантировать, что все различные комбинации аргументов работают правильно.

Пометить аргументы

Передача логического флага в функцию в качестве аргумента совершенно недопустима, это означает, что эта функция выполняет несколько действий в зависимости от значения этого флага, правильный способ - объявляя две отдельные функции, по одной для каждой цели, и вместо того, чтобы передавать флаг функции и проверять его значение внутри него и писать код для двух разных вещей, вы проверяете значение и вызываете две созданные вами функции .

Диадические и триадические функции

проблема с ними, порядок параметров, когда вы вызываете функцию, вы, возможно, пропустите аргументы порядка, вы можете объявить функцию, как это имя_функции (ar1, ar2, ar3), но вы называете ее как это имя_функции (ar1, ar3, ar2), порядок аргументов не имеет значения, чтобы вы могли предсказать, какие параметры вы должны передать в первую очередь, в некоторых современных языках программирования эта проблема решается с помощью Именованного аргумента , который предоставляет вам способ отправить значение для определенного имени и не зависит от порядка, в котором вы передаете аргументы.

или вы можете использовать старое решение, которое кодирует имя аргумента в имя функции, чтобы не запоминать порядок аргументов, например writeTextIntoPath (текст, путь) вместо записи (текст, путь)

Объекты аргумента

Когда функции требуется более двух или трех аргументов (полиадические), рекомендуется обернуть эти аргументы в класс и отправить его экземпляр.

Не используйте входы как выходы

Использование выходного аргумента вместо возвращаемого значения для преобразования сбивает с толку. Если функция собирается преобразовать свой входной аргумент, в качестве возвращаемого значения должно появиться преобразование. и Не изменять глобальную переменную, вернуть новую.

Без побочных эффектов

Функция не должна изменять никаких неожиданных вещей, она просто делает то, что должна делать (делать одно дело), ​​а побочные эффекты, исходящие от функции, обещают сделать что-то одно. , но он также выполняет другие скрытые функции.

Обработка ошибок

Обработка ошибок - это одно дело, функция, которая обрабатывает ошибки, не должна делать ничего другого. Если ключевое слово try существует в функции, оно должно быть самым первым словом в функции и после блоков catch / finally ничего не должно быть.

НЕ ПОВТОРЯЙТЕ СЕБЯ (СУХОЙ)

все это касается удаления дублирующего кода. Где бы вы ни находили какой-то код, который вы повторяете и используете в разных местах, вы должны реорганизовать свой код и извлечь этот повторяющийся код для работы и использовать эту функцию вместо этого. Это заставляет изменить код выполнен в одном месте, а также уменьшает размер кода.

Однократный въезд - ›Правило однократного выхода.

функция должна иметь один вход и один выход. это означает, что в функции должен быть только один оператор возврата, никаких операторов break или continue в цикле и никогда не должно быть никаких операторов goto. Это только в большие функции это правило дает преимущества, поэтому, если вы сохраняете свои функции маленькими, то многократные инструкции return, break или continue не причинят вреда, а иногда могут быть даже более выразительными.

В конце концов, не беспокойтесь о том, чтобы начать писать свои функции длинными, сложными, с большим количеством отступов, вложенными циклами, длинными списками аргументов, дублированным кодом и произвольными именами, Вы можете улучшать свой код снова и снова, пока не будет невозможно сделать код лучше, чем он есть, со временем у вас будет чувство кода.