"Привет, мир"

Что такое дырявые абстракции? (Иллюстрированное руководство)

Абстракции - естественная часть разработки программного обеспечения, и утечки не обязательно являются плохими

Если вы сейчас осмотритесь, то обнаружите, что окружены очень сложными объектами. Смартфоны, компьютеры, принтеры, автомобили, телевизоры, тостеры - список можно продолжить. Но какими бы сложными ни были эти устройства, вы можете использовать их для того, что вам нужно, даже если вам будет сложно построить какое-либо из них самостоятельно.

Это маленькое чудо произошло благодаря принципу, который мы называем абстракцией . Абстракция - это философия дизайна, которая заменяет запутанный беспорядок сложных деталей аккуратным интерфейсом, который вы можете использовать для GSD (Get Stuff Done). Абстракция также работает глубоко в сердце каждой программы, пытаясь сдержать поток неразберихи. И время от времени эти абстракции начинают просачиваться.

В этой статье вы узнаете, что значит «дырявая» абстракция, почему они возникают и стоит ли вам, серьезному программисту, об этом беспокоиться.

Давайте снова введем абстракции

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

Вот как это работает. Обычный автомобиль имеет простой интерфейс вождения, состоящий примерно из этого: кнопка запуска, рулевое колесо для установки направления и две педали для управления скоростью. Вы используете кнопку запуска (или ключ), чтобы начать работу, даже если вы ничего не знаете о работе аккумуляторного стартера и газового двигателя внутреннего сгорания. (Версия для программистов: вы вызываете метод Car.Start().) Вы используете рулевое колесо, чтобы указывать на себя в разных направлениях, даже если вы не понимаете, как приводится в действие рулевая колонка или как соединяются колеса. И так далее.

То же самое и с компьютерами. Вы можете посетить веб-сайт, введя веб-адрес в соответствующее поле. Вам не нужно понимать, как выполняется поиск DNS, чтобы найти нужный веб-сайт, или как ваше устройство выполняет квитирование TCP с удаленным веб-сервером, чтобы они могли общаться. Что хорошо, потому что эти процессы достаточно детализированы.

Со временем мы создаем новые абстракции и добавляем к уже существующим. Когда люди впервые проектировали автомобили, в интерфейсе не было спидометра (из слов программистов: не было свойства Car.CurrentSpeed). Но оказывается, что очень сложно заставить автомобильные объекты подчиняться статическому свойству Road.MaxSpeed без него. Поэтому они добавили его в следующей версии, и с тех пор жизнь изменилась.

Создавать что-либо - что угодно - значит думать о создании правильной абстракции. Хорошая абстракция - это такая абстракция, которая раскрывает все важные детали и ничего лишнего. Тот, который уравновешивает контроль и сложность. Тот, который предоставляет методы и свойства, которые легко сопоставляются с задачами, которые вы хотите выполнить. Если абстракция спроектирована хорошо, ее использование кажется простым и логичным.

При программировании программного обеспечения этот процесс становится более очевидным. Если вы пишете код, который что-то делает, вам нужно подумать о том, как скрыть его внутреннюю работу от других фрагментов кода и как раскрыть нужную функциональность. Шаблоны тестирования, именования и проектирования - все это часть гигантских усилий по принятию правильных решений при построении абстракций и удержанию их эффектов под контролем.

Абстракции - вот почему вы можете писать <button> в документе HTML вместо того, чтобы рисовать отдельные пиксели. Вот почему вы можете написать SQL-запрос для получения истории заказов клиента, не зная размера каждой записи о том, где она хранится. Вот почему вы можете распечатать файл, не понимая языка принтера, воспроизвести видеофайл без понимания видеокодеков, прочитать текстовый файл без ручного перехода с одного кластера на другой на жестком диске и хранить коллекции данных без управления адресами памяти (если вы не действительно хочу).

Было бы преувеличением сказать, что все хорошее в программировании происходит от абстракции ... но только от малейшей.

Как утекают абстракции

Центральная истина: Все абстракции просачиваются.

Его иногда называют Законом дырявых абстракций после того, как он был придуман одним из создателей Stack Overflow Джоэлом Спольски. Но почему существует это правило? Почему мы не можем построить идеальную абстракцию?

Проблема в том, что ценность абстракции заключается в деталях, которые она скрывает. Каждая хорошая абстракция хочет упростить жизнь и должна скрыть некоторые детали вне поля зрения (и вне досягаемости вашего кода). В конце концов, появляются крайние случаи, особые сценарии, новые функции или необычные проблемы, которые можно решить только с помощью этих скрытых деталей. Этот момент, когда некоторые детали выплескиваются за пределы абстракции, и вам нужно вмешиваться во внутреннюю работу, и есть утечка.

Вернемся к нашему примеру с автомобилем. Вы можете создать красивый интерфейс с fillGas() и changeOil() интерфейсами. Но затем забивается радиатор, двигатель перегревается, и пора отгонять дым и копаться во внутренних механизмах автомобиля. Пользовательский интерфейс автомобиля не подходит для этой работы. Вместо этого вам нужен механик, который понимает все детали, которые скрывает эта абстракция.

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

Если все это звучит слишком похоже на дзен ремонта автомобилей и не очень похоже на программирование, рассмотрите некоторые из этих дырявых абстракций в разработке программного обеспечения:

  • Переменные класса. Вы назначаете их как обычные значения, но пытаетесь сравнить или копировать их, и внезапно вы сравниваете или копируете ссылку памяти, а не объект. сам. Следующее, что вы знаете, вам нужно знать о стеке и куче, тех самых подробностях, которых вы избегали.
  • Числа JavaScript. Что вы получаете, когда запускаете console.log(0.1+0.34)? Одна ненадежная абстракция с плавающей запятой. Чтобы исправить это, вам нужно узнать об арифметике с плавающей запятой, рассмотреть возможность округления или, возможно, использовать BigInt.
  • Сопоставление объектных отношений в базе данных. Используйте структуру ORM, и вы можете работать с объектами вместо таблиц, запросов и хранимых процедур (которые сами по себе уже являются абстракцией над хранилищем данных). Но базы данных используются интенсивно, производительность становится важной, и вскоре вам понадобится детальный контроль, который заставит вас охватить абстракцию ORM.
  • Веб-формы ASP.NET. Это всего лишь один пример серверной инфраструктуры, которая пытается заставить вас забыть, что ваш код на самом деле выполняется на другом компьютере (веб-сервере). Проблема в том, что большинство веб-приложений вскоре потребуют тщательного анализа скорости отклика, задержки и размера страницы. Когда они появятся, вам нужно будет узнать все кровавые подробности о реализации модели выполнения вашего веб-фреймворка и о разнице между клиентским и серверным кодом.

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

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

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