Природа программного обеспечения состоит в том, чтобы постоянно развиваться. Если не шутить про COBOL, то редко можно встретить фреймворки программирования, которые достигают такого уровня зрелости и поддержки, который позволяет им просто существовать, не будучи вытесненными новым языком или лучшей абстракцией. Что само по себе замечательно. Кому хочется писать программное обеспечение, соответствующее ожиданиям сегодняшнего дня, выполняя при этом задачи ручного управления памятью или манипулируя строками, которые представляют собой просто сырые указатели в блоке памяти, завершающиеся нулевым символом (\0)?
Но иногда в этом постоянно развивающемся пространстве находишь некий фреймворк, который находит отклик у тебя в душе и за который начинаешь крепко держаться. Я хотел бы поделиться тем, как это произошло со мной, сначала с Ruby (что неудивительно), а затем, как ни странно, с Objective-C.
Путешествие
Знакомство с Ruby было похоже на разворачивание вложенных друг в друга подарков:
- «Подождите?! Всё — объекты?!» — Запуск 1.next в консоли IRB до сих пор вызывает у меня смех
- «Who’s _why? » — я все еще предпочитаю Poignant Guide к Pickaxe.
- «Не может быть. Вы не можете создать блог за 15 минут?» — Rails открыл мне конвенцию над конфигурацией, шаблон активной записи, шаблон model-view-controller и разработку через тестирование — и все это одновременно.
Но потом появился iPhone, и все захотели написать для него «приложение», и я в том числе. Но была одна загвоздка: писать его нужно было на Objective-C. Если вы считаете, что сегодня этот язык малоизвестен, посмотрите индекс TIOBE по Objective-C за 2007 год, когда был выпущен iPhone.
Кроме того, знакомство с Objective-C начиналось немного сложнее:
- «Что?! Я все время ввожу квадратные скобки? Что это такое?!» — Objective-C — это C, расширенный новыми способами с помощью квадратных скобок.
- «Почему все классы начинаются с букв ‘NS’?» — Пространства имен нет, поэтому, чтобы избежать коллизий, добавляйте префикс ко всем именам ваших классов.
- «Где мой сборщик мусора?» — Вы все еще на C, так что или следите за циклами retain/release, или получайте segfault и плачьте.
Но после того как вы вытрете слезы и пыль осядет, вы сможете понять, что у Ruby и Objective-C действительно много общего:
- В Ruby есть Object, от которого отпочковываются все классы, в Objective-C — NSObject.
- В Ruby есть Proc для передачи методов, в Objective-C — блоки.
- В Ruby есть открытые классы для «обезьяньих» исправлений, в Objective-C есть Category и Extensions для того же самого.
- В Ruby есть Object#respond_to_missing? и Object#method_missing для метапрограммирования, в Objective-C есть аналогичные NSObject#respondsToSelector и NSObject#performSelector
- В Ruby есть Object#send для отправки необработанных динамических сообщений объектам, в Objective-C каждое сообщение проходит через objc_msgSend
- Ruby имеет методы рантайма/рефлексии для запроса объектов и изменения переменных экземпляра, такие как Object#methods и Object#instance_varaible_set, Objective-C также позволяет напрямую взаимодействовать с рантаймом.
Архитектурно они действительно имеют достаточно много общего, поэтому за прошедшие годы было предпринято довольно много попыток соединить их. Самая ранняя из них, которую я обнаружил, относится к 2001 году и была создана в рамках проекта GNUstep — открытой реализации фреймворков Apple Objective-C и Cocoa.
С тех пор многое изменилось как в мире Ruby, так и в мире Objective-C, но я был удивлен, что после некоторых доработок, направленных на вызов современных версий кода расширения Ruby C и среды исполнения Objective-C, а также адаптации к 64-битным архитектурам, код проекта работает на современных версиях macOS и Ruby. Это действительно свидетельство того, что среда выполнения Objective-C (и API расширения Ruby C), несмотря на то, что большая часть оригинального кода была написана в 2001 году, работает без изменений более 20 лет спустя на современных версиях macOS и Ruby.
Мне не нужно ваше кресло-качалка
Не стоит забывать, что в настоящее время в 2023 году Objective-C занимает в индексе TIOBE место рядом с COBOL (позиции 25 и 26 соответственно). В 2014 году компания Apple обратила внимание на Swift и больше не оглядывалась назад. Однако даже сегодня, в iOS 16, Apple в более чем 66% собственных двоичных файлов по-прежнему использует Objective-C. Язык достиг того уровня зрелости и поддержки, который позволяет ему просто продолжать работать в фоновом режиме.