The Law of Leaky Abstractions (2002)
В этой статье Джоэл Спольски формулирует один из важнейших принципов разработки программного обеспечения, который он назвал Законом дырявых абстракций. Ниже представлен подробный пересказ основных идей статьи.
Суть абстракции на примере TCP/IP
Автор начинает с примера работы интернета. Протокол TCP позволяет передавать данные надежно: сообщение гарантированно дойдет в целости и в правильном порядке. Однако TCP построен поверх протокола IP, который по своей природе ненадежен — пакеты могут теряться, приходить в неверном порядке или заменяться мусором.
TCP создает абстракцию — упрощенную модель сложной реальности. Он «притворяется» надежным каналом, скрывая под капотом сложную механику исправления ошибок и повторной отправки данных.
Закон дырявых абстракций
Несмотря на удобство, любая абстракция иногда дает сбой. Если сетевой кабель перерезан или хаб перегружен, «надежность» TCP исчезает: передача данных либо прекращается, либо становится очень медленной. В этот момент реальность «просачивается» сквозь упрощенную модель. Спольски формулирует свой закон так:
«Все нетривиальные абстракции в той или иной степени текут».
Примеры «протечек» в программировании
Автор приводит несколько ярких примеров того, как абстракции подводят разработчиков:
- Двумерные массивы: Итерация по большому массиву может быть в тысячи раз медленнее, если обходить его вертикально, а не горизонтально. Это происходит из-за «протечки» абстракции виртуальной памяти, вызывающей ошибки страниц (page faults).
- SQL: Язык запросов должен скрывать процедурные шаги, позволяя лишь описывать результат. Но на практике некоторые эквивалентные запросы работают в разы быстрее других, заставляя программиста изучать план выполнения запроса и внутренности базы данных.
- Сетевые файловые системы (NFS): Они позволяют работать с удаленными файлами так, будто они локальные. Но как только сеть падает, эта иллюзия рушится, и программа, не рассчитанная на сетевые задержки, ломается.
- Строки в C++: Попытка сложить два строковых литерала (
"foo" + "bar") не сработает, так как абстракция «строки как базового типа данных» дает течь, обнажая лежащие в основе указателиchar*. - ASP.NET: Эта технология пытается скрыть разницу между нажатием на кнопку и ссылкой, используя JavaScript. Если у пользователя отключен JavaScript, абстракция «течет», и приложение перестает работать правильно.
Главный парадокс: почему учиться становится сложнее
Самый важный вывод Спольски заключается в том, что абстракции экономят наше время в работе, но не экономят время на обучение.
Когда появляется новый инструмент для генерации кода или высокоуровневый фреймворк, он упрощает выполнение типичных задач. Но как только абстракция дает течь (а она обязательно даст), программист обязан знать, как все устроено на уровнях ниже, чтобы исправить проблему.
Это ведет к парадоксу: хотя инструменты становятся всё более высокоуровневыми, стать профессиональным программистом становится всё труднее. Сегодня разработчику недостаточно знать Visual Basic или современный фреймворк; он по-прежнему должен понимать указатели, работу памяти, протоколы и другие низкоуровневые концепции, иначе он окажется в тупике при первой же серьезной ошибке.
Вывод: Абстракции позволяют нам справляться с огромной сложностью современных систем, но они не избавляют нас от необходимости понимать основы программирования.