Рубрики
Без рубрики

Простой подход к созданию более надежной системы

“Система не должна выходить из строя, и приложение не должно выходить из строя. ” Эта мантра получила широкое распространение… С пометкой “Производительность”, “дизайн”, “java”.

“Система не должна выходить из строя, и приложение не должно выходить из строя”. Эта мантра широко применяется при разработке программного обеспечения и проектировании распределенных систем. Различные компании внедрили какие-то методы для предотвращения сбоя своего приложения. Например, Amazon защищает свою облачную инфраструктуру от сбоев с помощью ” высокодоступная система “, которая относится к системе без единой точки отказа – путем создания избыточности, чтобы в случае сбоя одного компонента система могла оставаться в рабочем состоянии. Facebook использует разделение своей базы данных MYSQL на каждый регион при первом запуске, чтобы предотвратить сбой их приложения. Однако, как и все люди, совершающие ошибки, вся система столкнется со сбоем. Существуют различные способы ограничить приложение, чтобы оно не выходило из строя, например, отсрочить сбой, найти обходной путь для устранения ошибок, чтобы система могла продолжать работать, и просто отключить его без сбоев. Эти методы – не лучший способ справиться с системным сбоем.

Почему? Потому что выполнение этих трех действий не решило проблему. Ошибка все еще существует. Сокрытие проблемы просто приведет к тому, что в будущем проблема станет еще больше, и на ее устранение потребуется больше времени и ресурсов.

Итак, что нам делать, если приложение выходит из строя?

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

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

Быстро терпит неудачу, вместо Безотказный

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

public int maxRent() {
  RentPortfolio rent = Portfolio.get("rent-portfolio");
  if(rent == null) {
    return 1000;
  } 
  return rent.getMaxPrice();
}

Этот метод вычисляет максимальную арендную плату, получая свойство rent-portfolio из объекта Portfolio . Когда вы вводите какое-либо значение в этот метод, оно будет возвращено корректно.

Теперь представьте, что в классе Portfolio произошло небольшое обновление, и один разработчик, который обновляет кодовую базу, создает единственную опечатку в rent-portfolio в rent-portfolio . Программное обеспечение по-прежнему будет успешно отправлено, и приложение по-прежнему будет работать. Однако пользователь каждый раз будет получать неправильное значение, так как он будет возвращать значение по умолчанию. Когда клиент поймет, что это неточно, будет трудно отладить проблему.

Вместо этого, если вы напишете безотказный метод:

public int maxRent() {
  RentPortfolio rent = Portfolio.get("rent-portfolio");
  if(rent == null) {
    throw new PortfolioNotFoundException("rent-portfolio is not found in " + this.portfolioPath);
  }
  return rent.getMaxPrice();
}

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

Еще один пример безотказного и безотказного метода:

Безотказный

public division(int numerator, int denominator) {
  /* some code here ........ */
  return numerator / denominator;
}

public static void main(String...args) {
  division(2,0);
}

Исключение: java.lang. ArithmeticException:/на ноль …

Быстрый отказ

public division(int numerator, int denominator) {
  if(denominator == 0) throw new IllegalArgumentException("denominator cannot be 0");
  /* some code here ..... */
  return numerator / denominator;
}

public static void main(String...args) {
  division(2,0);
}

Исключение: java.lang. Исключение IllegalArgumentException: знаменатель не может быть равен 0 ….

В этом примере fail-fast действительно выдает ошибку. Однако приложение выдает неправильное сообщение. Основная причина ошибки заключается в том, что это Исключение InvalidArgumentException вместо ArithmeticException . Таким образом, разработчику необходимо несколько раз просмотреть код, чтобы понять, в чем заключается проблема. Отказоустойчивость поможет разработчику, который поддерживает программу, немедленно обнаружить ошибку.

Советы – Пара Неудачных Быстрых проверок:

  • Нулевой
  • Пустая Строка
  • Пустой список
  • Большинство проверок предварительных условий

Способы выявления видимого сбоя:

  • Использование разработки, основанной на тестировании. вы сможете указать успешный вариант использования и неудачный вариант использования с помощью утверждения еще до того, как вы реализуете свой метод.
  • Наличие встроенной непрерывной интеграции в вашем процессе разработки программного обеспечения обеспечит любой необходимый сбой при объединении ветви функций с основной ветвью.
  • Создание утверждения для проверки работоспособности – разницу между утверждением и исключением можно найти здесь (ссылка).
  • Когда возникает какая-либо проблема с настройкой системы, вместо того, чтобы использовать резервную функцию, отключите систему, чтобы вы могли получить уведомление и немедленно устранить проблему.
  • Когда интерфейс запрашивает вызов GET для коллекции на сервер, вместо возврата пустого списка, когда он не найден, возвращает исключение 404 not found.

Возвращайтесь пораньше

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

public String getPersonalData(Person person) {
  if(!systemIsUp) {
   if(person.getName() == "") {
    if(person.age == 0) {
      if(person.pin == "") {
        return "Person doesn't have a pin"; 
      }
      return "Person age cannot be 0";
    }
    return "Person Doesn't have a name"
   }
   return "System is Down"
  }

  return person.getName();
}

Если вы читаете этот код, то к тому времени, когда вы перейдете к третьему утверждению, вы можете забыть, каким должно быть утверждение двух предыдущих аргументов. Основная проблема с этой проверкой заключается в том, что ее не только трудно отлаживать, когда что-то выходит из строя, но и трудно читать. Это приводит к высокой цикломатической сложности. Цикломатическая сложность – это показатель, который измеряет, насколько сложна ваша программная система. Как вы измеряете сложность? Всякий раз, когда есть if , else , try , catch , for , и , или , others , while , вы добавляете небольшая сложность. Более высокая цикломатическая сложность означает, что система сложна и ее трудно поддерживать. Кроме того, отслеживание всех проверок и вложенных инструкций if/else трудно сохранить в вашей памяти. Вместо этого верните предварительно обусловленный оператор if/else раньше, сначала начиная с простого условия.

public String getPersonal(Person person) {
  if(!systemIsUp) return "System is Down";

  if(person.getName() == "") return "Person Doesn't have a name";

  if(person.age == 0) return "Person age cannot be 0";

  if(person.pin == 0) return "Person' doesn't have a pin";

  return person.getName();
} 

Если вы читаете этот код, вы поймете, каким должно быть предварительное условие. Вам не нужно иметь лист бумаги и писать все инструкции if/else, когда вы отлаживаете приложение. Кроме того, в функцию записывается меньше кода.

Блюда на вынос

“Неудачи, повторяющиеся неудачи – это указательные знаки на пути к достижению. Человек терпит неудачу, двигаясь вперед к успеху”. К.С. Льюис.

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

Ссылка:

Оригинал: “https://dev.to/edwardgunawan/the-simple-approach-to-create-a-more-robust-system-326f”