Редкие случаи (edge cases) в разработке: проблемы на граничных параметрах, вызванные нетипичным поведением, сложностью систем и ограничениями ресурсов. Тестирование важно!
Сравнивайте с английским: нажмите на абзац — оригинал откроется в окне. Кнопка EN под абзацем показывает его прямо в тексте.
Введение
Проблема или ситуация, возникающая только при экстремальных рабочих параметрах.
Problem or situation that occurs only at an extreme operating parameter
Крайний случай – это проблема или ситуация, возникающая только при экстремальных (максимальных или минимальных) рабочих параметрах. Например, стереодинамик может заметно искажать звук при воспроизведении на максимальной громкости, даже при отсутствии других экстремальных настроек или условий. Крайний случай может быть предсказуемым или неожиданным. В инженерии планирование и корректная обработка крайних случаев может быть сложной задачей, которую часто упускают из виду или недооценивают. Некоторые распространенные причины возникновения крайних случаев:
An edge case is a problem or situation that occurs only at an extreme (maximum or minimum) operating parameter. For example, a stereo speaker might noticeably distort audio when played at maximum volume, even in the absence of any other extreme setting or condition. An edge case can be expected or unexpected. In engineering, the process of planning for and gracefully addressing edge cases can be a significant task, and yet this task may be overlooked or underestimated. Some common causes of edge cases are:
Непредсказуемое поведение пользователей.
Эволюция сценариев использования (например, поведение пользователей может меняться со временем).
Недостаточное покрытие тестами.
Сложность продукта (например, в распределенных системах или микросервисной архитектуре).
Ограничения ресурсов (например, ограниченная вычислительная мощность, память компьютера или объем хранилища).
Другие внешние факторы.
Unpredictable user behavior
Evolution of use cases (e. g. user behavior may change over time)
Limited test coverage
Product complexity (for instance, in distributed systems or microservice architectures)
Resource limitations (e. g. limited processing power, computer memory, or computer storage)
Other external causes
Некоторые простые примеры крайних случаев:
Some basic examples of edge cases include:
Длинное имя пользователя в приложении вызывает переполнение и отображается некорректно.
Система бронирования некорректно обрабатывает резервации в високосный год (29 февраля).
A long username in an app overflows and displays incorrectly
A booking system does not handle reservations correctly on a leap day (February 29th)
Нетривиальные крайние случаи могут привести к отказу разрабатываемого объекта. Они могли быть не учтены на этапе проектирования и считаться невозможными при нормальной эксплуатации объекта. Поэтому попытки формализации хороших инженерных стандартов часто включают информацию о крайних случаях.
Non trivial edge cases can result in the failure of an object that is being engineered. They may not have been foreseen during the design phase, and they may not have been thought possible during normal use of the object. For this reason, attempts to formalize good engineering standards often include information about edge cases.
Инженеры программного обеспечения
В программировании крайний случай обычно связан с входными значениями, требующими специальной обработки в алгоритме компьютерной программы. В качестве способа проверки поведения компьютерных программ в таких случаях обычно создаются модульные тесты; они проверяют граничные условия алгоритма, функции или метода. Серия крайних случаев вокруг каждой "границы" может быть использована для обеспечения разумного покрытия и уверенности, исходя из предположения, что если программа корректно обрабатывает граничные значения, она должна корректно работать и в других случаях. Например, функция, делящая два числа, может быть протестирована с использованием как очень больших, так и очень маленьких чисел. Это основано на том, что если она работает для обоих пределов диапазона значений, она должна работать правильно и между ними. Программисты также могут создавать интеграционные тесты для обработки крайних случаев, не охваченных модульными тестами. Эти тесты охватывают случаи, которые проявляются только при тестировании системы в целом. Например, модульный тест может гарантировать, что функция правильно вычисляет результат, а интеграционный тест гарантирует, что эта функция работает правильно при интеграции с базой данных или внешним API. Эти тесты особенно важны с учетом растущей сложности систем в распределенных системах, микросервисах и устройствах Интернета вещей (IoT). В частности, тестирование микросервисов становится сложной задачей, поскольку интеграционные тесты могут не охватывать все конечные точки микросервисов, что приводит к необработанным крайним случаям. К другим типам тестирования, связанным с крайними случаями, относятся нагрузочное тестирование и негативное/отказоустойчивое тестирование. Оба метода направлены на расширение покрытия тестами системы, снижая вероятность возникновения неожиданных крайних случаев. В процессе разработки, управляемой тестированием, крайние случаи могут быть определены системными требованиями и учтены в тестах до написания кода. Такая документация может быть включена в документ с требованиями к продукту после обсуждения с заинтересованными сторонами и другими командами.
In programming, an edge case typically involves input values that require special handling in an algorithm behind a computer program. As a measure for validating the behavior of computer programs in such cases, unit tests are usually created; they are testing boundary conditions of an algorithm, function or method. A series of edge cases around each "boundary" can be used to give reasonable coverage and confidence using the assumption that if it behaves correctly at the edges, it should behave everywhere else. For example, a function that divides two numbers might be tested using both very large and very small numbers. This assumes that if it works for both ends of the magnitude spectrum, it should work correctly in between. Programmers may also create integration tests to address edge cases not covered by unit tests. These tests cover cases which only appear when a system is tested as a whole. For example, while a unit test may ensure that a function correctly calculates a result, an integration test ensures that this function works properly when integrated with a database or an external API. These tests are particularly relevant with increasing system complexity in distributed systems, microservices, and Internet of things (IoT) devices. With microservices in particular, testing becomes a challenge as integration tests may not cover all microservice endpoints, resulting in uncovered edge cases. Other types of testing which relate to edge cases may include load testing and negative/failure testing. Both methods aim at expanding the test coverage of a system, reducing the likelihood of unexpected edge cases. In test driven development, edge cases may be determined by system requirements and accounted for by tests, before writing code. Such documentation may go inside a product requirements document after discussions with stakeholders and other teams.