Вопрос

Мне кажется, что самое бесценное в статическом / строго типизированном языке программирования - это то, что он помогает в рефакторинге:если / когда вы измените какой-либо API, компилятор сообщит вам, что это изменение нарушило.

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

Это правда?

Это было полезно?

Решение

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

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

Основное ограничение статических типов заключается в том, что они ограничены в ограничениях, которые они могут выражать.Это зависит от языка, причем большинство языков имеют относительно простые системы типов (c, java), а другие - чрезвычайно мощные системы типов (haskell, cayenne).

Из-за этого ограничения типов самих по себе недостаточно.Например, в java типы более или менее ограничены проверкой совпадения имен типов.Это означает, что значение любого ограничения, которое вы хотите проверить, должно быть закодировано в какую-либо схему именования, отсюда и множество косвенных ссылок и общая для кода Java табличка.C ++ немного лучше в том смысле, что шаблоны обеспечивают немного большую выразительность, но и близко не подходят к тому, что вы можете сделать с зависимыми типами.Я не уверен, в чем заключаются недостатки более мощных типовых систем, хотя очевидно, что должно быть несколько человек, которые будут использовать их в промышленности.

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

Что касается вашего второго вопроса:

Как мы можем безопасно изменить фактор на языке, типизированном во время выполнения?

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

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

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

Другие советы

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

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

Я думаю, что внутренние инструменты Google на самом деле выполняют компиляцию и, вероятно, проверку типов в своем Javascript.Жаль, что у меня нет таких инструментов.

Начнем с того, что я родной программист на Perl, поэтому, с одной стороны, я никогда не программировал с использованием сети статических типов.OTOH Я никогда не программировал с их помощью, поэтому не могу говорить об их преимуществах.О чем я могу поговорить, так это о том, каково это - проводить рефакторинг.

Я не считаю, что отсутствие статических типов является проблемой при рефакторинге.Что я нахожу проблемой, так это отсутствие рефакторинга браузер.Проблема динамических языков заключается в том, что вы действительно не знаете, что на самом деле будет делать код, пока вы его на самом деле не запустите.У Perl этого больше, чем у большинства.У Perl есть дополнительная проблема, связанная с наличием очень сложного, почти неразрешимого синтаксиса.Результат:никаких инструментов рефакторинга (хотя они очень быстро работают над этим).Конечный результат заключается в том, что мне приходится проводить рефакторинг вручную.И это то, что приводит к ошибкам.

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

Статические типы, как это предусмотрено в Java, C ++ или C #, на самом деле решают лишь небольшой класс задач программирования.Они гарантируют, что вашим интерфейсам передаются биты данных с правильной меткой.Но только потому, что вы получаете Коллекцию, не означает, что эта коллекция содержит те данные, о которых вы думаете.То, что вы получаете целое число, не означает, что вы получили правильное целое число.Ваш метод принимает объект User, но вошел ли этот пользователь в систему?

Классический пример: public static double sqrt(double a) является ли подпись для функции квадратного корня Java.Квадратный корень не работает с отрицательными числами.Где это сказано в подписи?Это не так.Что еще хуже, где сказано, что вообще делает эта функция?В подписи указано только, какие типы она принимает и что возвращает.В нем ничего не говорится о том, что происходит между ними, и именно там живет интересный код.Некоторые люди пытались использовать полный API с помощью проектирование по контракту, который в широком смысле можно описать как встраивание тестов входных данных, выходных данных и побочных эффектов вашей функции во время выполнения (или их отсутствия)...но это уже другое шоу.

API - это гораздо больше, чем просто сигнатуры функций (если бы это было не так, вам не понадобилась бы вся эта описательная проза в Javadocs), а рефакторинг - это гораздо больше, чем просто изменение API.

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

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

Одно из преимуществ использования var в C # 3.0 это то, что вы может часто меняйте тип, не нарушая никакого кода.Тип должен по-прежнему выглядеть одинаково - должны существовать свойства с теми же именами, методы с той же или похожей сигнатурой все еще должны существовать.Но вы действительно можете перейти на совсем другой тип, даже не используя что-то вроде ReSharper.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top