Как программисты, мы постоянно ищем языки, которые являются производительными, продуктивными и универсальными. Существует ли какой-либо язык программирования, который в настоящее время удовлетворяет этим свойствам? Сможем ли мы когда-нибудь создать его?

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

Определения

Компромисс программирования диктует, что язык программирования не может одновременно удовлетворять следующим желательным свойствам:

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

Компромиссы

Давайте сначала сосредоточимся на компромиссе между производительностью и производительностью.

С одной стороны, некоторые языки, такие как C и ассемблер, работают ближе к аппаратному обеспечению и более производительны, чем их аналоги. С другой стороны, другие языки, такие как LISP и Python, предоставляют множество удобных функций, повышающих производительность труда программистов.

Мы можем вывести следующие правила, чтобы обобщить эти наблюдения:

Язык программирования является эффективным тогда и только тогда, когда язык предоставляет набор функций, близких к логике компьютера.

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

Поскольку логика компьютера отличается от логики программиста, задача оптимизации как производительности, так и производительности языка программирования невозможна.

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

Мы видим, что компромисс программирования — это прямое применение техники разделяй и властвуй к созданию языков программирования. Например, SQL имеет одну и единственную цель: управление информацией базы данных на основе семантики реляционной алгебры. Другие предметно-ориентированные языки (DSL) созданы для решения узких задач, таких как веб-шаблоны (Jinja), манипуляции с матрицами (numpy) или логическое программирование (Prolog).

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

Сообщение на дом

Если игнорировать программный компромисс, это может навредить успеху программных проектов.

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

Facebook и Twitter столкнулись с той же проблемой и были вынуждены масштабировать свои веб-сайты, не жертвуя своей способностью разрабатывать новые функции.

Во всех этих случаях большинство языков программирования не помогают, поскольку они либо слишком медленны для выполнения (например, Python, R), либо слишком медленны для разработки (Java, C++).

Наиболее распространенным решением этой проблемы часто является переписывание приложения на другом (и часто несовместимом) языке.

Другие решения могут уменьшить необходимость переписывать существующие приложения:

  • Создавайте и исследуйте языки программирования для конкретных целей (например, языки запросов, конвейеры данных, парадигмы программирования…)
  • Используйте полиглот-программирование, чтобы объединить силу нескольких языков (например, TensorFlow опирается как на C++ для производительности, так и на Python).
  • Помните, что преждевременная оптимизация — корень всех зол, зачастую важнее изучить крайние случаи проблемы, прежде чем оптимизировать узкий путь.
  • Помните, что требования проекта со временем меняются, способность адаптироваться к новым требованиям остается важной в ходе проекта.