В программировании проблема под названием пирамида судьбы — это довольно распространённый случай, который возникает при структурировании программы путём вложения друг в друга множества однотипных конструкций для обеспечения корректности вычислений. Возникает довольно часто при проверке нулевых указателей или при обработке обратных вызовов. Два примера, имеющих отношение к данному термину, связанные с определённым стилем программирования в JavaScript, а также вложенные друг в друга операторы if в ООП языках когда один из объектов может иметь нулевой указатель.
Примеры Современные объектно-ориентированные языки программирования предлагают стиль кодирования, известный как точечное обозначение, позволяющий вызывать несколько методов подряд в одной строке кода, путем отделения каждого вызова точкой. Например:
theWidth = windows("Main").views(5).size().width();
Данный код содержит четыре отдельные команды. Сначала в коллекции окон находится окно с именем «Main», затем среди изображений внутри данного окна выбирается изображение номер 5, далее вызывается метод size, возвращающий структуру содержащую размеры данного изображения, и в заключение вызывается метод width для данной структуры, производящий результат, который помещается в переменную theWidth.
Проблема здесь состоит в том, что код отталкивается от факта существования каждого из перечисленных значений. Несмотря на то, что вполне резонно ожидать наличия размеров у каждого изображения, а также ширины у каждого размера, мы никогда не можем гарантировать ни существование окна с именем «Main», ни того что у него будет пять изображений. Если одно из вышеперечисленных обстоятельств не будет иметь места, один из методов будет применён к нулевому указателю, что приведёт к ошибке.
Чтобы избежать ошибки, программист вынужден проверять существование объекта перед каждым следующим вызовом. Безопасная версия кода может выглядеть так: if windows.contains("Main") { if windows("Main").views.contains(5) { theWidth = windows("Main").views(5).size().width(); //далее код, использующий theWidth
Если программист желает использовать это значение различным образом, в зависимости от того существует ли оно или нет, то в таком случае весь полезный код внутри конструкции if будет существенно смещён вправо, что приводит к трудностям при чтении кода. Это вынуждает применять «плоские» конструкции, например: if windows.contains("Main") { theWindow = windows("Main") } if theWindow != null && theWindow.views.contains(5) { theView = theWindow.views(5) } if theView != null { theWidth = theView.size().width(); //дальнейший код }
или: if !windows.contains("Main") { // обработчик ошибки } else if !windows("Main").views.contains(5) { // обработчик ошибки } else { theWidth = windows("Main").views(5).size().width(); //далее код, использующий theWidth }
Конструкции подобного рода весьма распространены и некоторые языки программирования в настоящее время предлагают некоторое подобие синтаксического сахара для борьбы с данным явлением. Например, в Apple Swift реализована концепция оператора безопасной навигации в операции if. В то же время в Microsoft C# 6.0 и Visual Basic 14 добавлены элвис-операторы ?. и ?[ для доступа к членам класса и индексирования, соответственно. Основная идея — позволить цепочке вызовов методов возвратить null немедленно, как только встретится отсутствующий объект, например код: theWidth = windows("Main")?.views(5)?.size.width; должен присвоить null переменной theWidth если либо «Main», либо пятое изображение отсутствуют, либо завершить вычисление и вернуть ширину в том случае если они оба существуют. Во многих ситуациях программист должен выполнять различные действия в двух вышеперечисленных случаях, поэтому Swift предлагает дополнительный синтаксический сахар для данных обстоятельств: выражение if let, известное также под именем «необязательная привязка»: if let theView = windows("Main")?.views(5) { //код если view существует... theWidth = theView.size.width }
Ссылки
Категория:Разработка программного обеспечения