Возможен ли автоматический рефакторинг в динамических языках?
Возможно, я ограничен опытом работы с динамическими языками (Ruby для Netbeans и Groovy для Eclipse), но мне кажется, что природа динамических языков делает невозможным рефакторинг (переименование методов, классов, push-up, pull-down, и т. д.) автоматически.
Можно ли выполнить рефакторинг АВТОМАТИЧЕСКИ на любом динамическом языке (с помощью любой IDE/ инструмента)? Мне особенно интересны Ruby, Python и Groovy, а также то, как рефакторинг сравнивается со 100% автоматическим рефакторингом, доступным во всех Java IDE.
5 ответов
Учитывая, что автоматический рефакторинг был изобретен на динамическом языке (Smalltalk), мне пришлось бы сказать "Да".
В частности, Джон Брант, Дон Робертс и Ральф Джонсон разработали Refactoring Browser, который является одним из основных инструментов, например, в Squeak.
Мой Google-фу сегодня слаб, но вы можете попытаться найти эту статью: Дон Робертс, Джон Брант и Ральф Джонсон, Refactoring Tool для Smalltalk, "Теория и практика объектных систем", (3) 4, 1997.
Smalltalk не объявляет никаких типов. Браузер рефакторинга успешно выполнил правильные рефакторинги в коммерческом коде с 1995 года и включен почти во все текущие среды разработки Smalltalk. - Дон Робертс
Автоматический рефакторинг был изобретен в Smalltalk, очень динамичном языке. И с тех пор это работает как шарм.
Вы можете попробовать себя в бесплатной версии Smalltalk (например, http://pharo-project.org/)
На динамическом языке вы также можете самостоятельно выполнить сценарий рефакторинга или запросить систему. Простой пример, чтобы получить количество тестовых классов:
TestCase allSubclasses size
Я удивился тому же. Я не пишу компилятор / интерпретатор, но думаю, что ответом будет то, что невозможно сделать его идеальным. Тем не менее, вы можете сделать это правильно в большинстве случаев.
Во-первых, я собираюсь изменить название "динамический" язык на "интерпретируемый" язык, о котором я думаю в Ruby, Javascript и т. Д. Интерпретируемые языки, как правило, используют преимущества возможностей времени выполнения.
Например, большинство языков сценариев допускают следующее
-- pseudo-code but you get the idea
eval("echo(a)");
Я просто "запустил" строку! Вы должны также рефакторинг этой строки. И будет ли переменная или этот язык позволяет печатать символ a без кавычек, если нет переменной a?
Я хочу верить, что этот вид кодирования, вероятно, является исключением, и вы будете получать хороший рефакторинг почти все время. К сожалению, кажется, что когда я просматриваю библиотеки для языков сценариев, они обычно попадают в такие исключения и, возможно, даже основывают свою архитектуру на них.
Или немного поднять ставку:
def functionThatAssumesInputWillCreateX(input)
eval(input)
echo(x)
def functionWithUnknownParms( ... )
eval(argv[1]);
По крайней мере, когда вы реорганизуете Java и меняете переменную с int на строку, вы получаете ошибки во всех местах, которые ожидали int:
String wasInt;
out = 3 + wasInt;
С интерпретированными языками вы, вероятно, не увидите этого до времени выполнения.
То же самое касается браузера Refactoring... он очень эффективен в Smalltalk. Однако я полагаю, что существуют определенные типы рефакторинга, которые были бы невозможны без информации о типах (независимо от того, получено ли это путем явной аннотации типов в языке или с помощью какой-либо формы вывода типов в динамическом языке). Один пример: при переименовании метода в Smalltalk он будет переименовывать всех разработчиков и отправителей этого метода, что чаще всего просто отлично, но иногда нежелательно. Если бы у вас была информация о типе переменных, вы могли бы охватить переименование только для разработчиков в текущей иерархии классов и всех отправителей, когда сообщение отправляется в переменную, объявленную как тип в этой иерархии (однако я мог бы представить сценарии где даже с объявлением типа это сломало бы и дало бы нежелательные результаты).