Есть много сильных мнений, окружающих дебаты, но, очевидно, это на самом деле не вопрос мнения, это вопрос фактов . Итак, мы должны смотреть на эмпирические исследования . И доказательства этого очевидны:
Да , статическая типизация стоит компромиссов - и не только немного, но на самом деле существенно . На самом деле, убедительные доказательства показывают, что статическая типизация может уменьшить количество ошибок в коде как минимум на 15% (и это низкая оценка, фактический процент почти наверняка больше). Это потрясающе высокое число: я думаю, что даже большинство сторонников статической типизации не подумали бы, что это имеет столь радикальное значение.
Подумайте об этом: если кто-то сказал вам, что существует простой способ уменьшить количество ошибок в вашем проекте на 15% за ночь, это должно быть просто.1 Это почти всем известная серебряная пуля.
Доказательства представлены в статье Печатать или не печатать: количественное определение обнаруживаемых ошибок в JavaScript » Чжэн Гао, Кристиана Берда и Эрла Т. Барра. Я призываю всех прочитать это, это хорошо написанная статья, которая представляет образцовое исследование.
Трудно кратко резюмировать, насколько строго авторы выполнили свой анализ, но вот (очень грубый) план:
TypeScript и Flow - это два языка программирования, основанные на JavaScript, которые, в остальном совместимые, добавляют подсказки типов и проверку статических типов. Это позволяет дополнять существующий код типами, а затем проверять его тип.
Исследователи собирали проекты с открытым исходным кодом, написанные на JavaScript, из GitHub, просматривали исправленные отчеты об ошибках и пытались свести каждую из сообщенных ошибок к коду, который будет обнаружен статической проверкой типов TypeScript или Flow. Это позволило им оценить нижнюю границу процента ошибок, которые можно исправить с помощью статической типизации.
Исследователи приняли строгие меры предосторожности, чтобы их анализ не рассматривал ошибку, не связанную с типом, как связанную с типами. 2
По сравнению с прошлыми исследованиями это новое исследование имеет особые преимущества:
- Существует прямое сравнение статической и динамической типизации с несколькими (если таковые имеются) смешивающими факторами, поскольку единственное различие между JavaScript и TypeScript / Flow - это типизация.
- Они выполняют репликацию по нескольким измерениям, проверяя и TypeScript, и Flow (т. Е. Системы разных типов), и заставляя разных людей воспроизводить (ручную) аннотацию типа для исправления ошибок. И они выполняют это на большом количестве кодовых баз из разных проектов.
- В статье измеряется прямое влияние статической типизации на исправляемые ошибки (а не на более неопределенное качество).
- Авторы заранее определяют строгую модель того, что и как измерять. Кроме того, их описание невероятно ясно и позволяет легко анализировать недостатки (это всегда хорошо, когда исследовательская работа раскрывает себя атакам: если никакие атаки не могут помешать ее аргументам, она выходит еще сильнее). 3
- Они выполняют надлежащий анализ мощности, чтобы их размер выборки был достаточным, а последующий статистический анализ - герметичным.
- Они чрезмерно консервативны, чтобы исключить смешные объяснения, и измеряют только одну движущуюся часть. Кроме того, они ограничивают свой анализ ошибками, которые могут быть немедленно исправлены путем включения типов, и исключают все, что может потребовать более сложного рефакторинга для обеспечения возможности ввода. Таким образом, на самом деле, эффект, вероятно, намного больше, но, конечно, не меньше, чем они сообщили.
- И, наконец, они не находят незначительного эффекта, но ошеломляют разницу. Несмотря на их чрезмерно консервативную процедуру, даже на нижнем уровне 95% -ного доверительного интервала они обнаруживают, что есть как минимум 10% ошибок, которые просто исчезают при минимальных проверках добавленных типов.
Если в статье нет фундаментального недостатка, который еще никто не обнаружил, статья окончательно демонстрирует большое преимущество статической типизации практически без затрат. 4
С исторической точки зрения, исследования по типизации дисциплин в программировании начались очень быстро, потому что в течение долгого времени доказательства были не совсем ясны. Причина этого в том, что проводить систематические эксперименты, чтобы исследовать эффект статической и динамической типизации, нелегко: систематический эксперимент должен изолировать эффект, который мы исследуем. И, к сожалению, мы не можем изолировать эффект от набора текста, поскольку он привязан к языкам программирования.
На самом деле были языки программирования, которые допускали как статическую, так и динамическую типизацию на разных диалектах (например, VB с Option Strict Onили Off, или статически типизированный Лисп). Тем не менее, они не очень подходили для прямого сравнения, что особенно важно, потому что не было существующих, достаточно больших баз кода, позволяющих проводить прямое сравнение. В лучшем случае мы могли бы сравнить их в «лабораторных условиях», где испытуемые случайным образом решают задачу в статически или динамически типизированном варианте языка.
К сожалению, эти задания искусственного программирования плохо моделируют использование в реальных условиях. В частности, многие из них невелики по объему и решают четко определенную проблему, которая может быть обобщена на половине страницы текста.
К счастью, это в прошлом, потому что TypeScript, Flow и JavaScript действительно являются одними и теми же языками, за исключением статической типизации, и потому что существует обширный реальный набор данных кода и ошибок для выборки.
1 Вдохновлен цитатой из оригинальной статьи.
2 Я не совсем доволен этим: одна из основных сильных сторон статически типизированных языков заключается в том, что якобы не связанные с типом проблемы могут быть сформулированы способами, которые могут быть статически проверены. Это преобразует многие логические ошибки в ошибки типов, что резко увеличивает количество ошибок, которые могут быть обнаружены статической типизацией. Фактически, статья грубо классифицирует ошибки, не связанные с типом, и я утверждаю, что большой процент из них может быть фактически обнаружен статической типизацией.
3 Я приглашаю любого, особенно сторонников динамической типизации, попытаться найти нерешенные недостатки в анализе. Я не думаю, что их много (если таковые имеются), и я уверен, что никакой потенциальный недостаток существенно не изменит результат.
4 Я подозреваю, что фактическая стоимость статической типизации в реальных крупномасштабных проектах не существует, поскольку тогда она становится естественной частью архитектуры и может даже упростить планирование. Исправление ошибок статического типа требует времени, но намного меньше, чем ошибки, обнаруженные позже. Это было тщательно изучено эмпирически и известно десятилетиями (см., Например, Code Complete ).