Как избежать типичных «динамических языковых ошибок»?

42

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

Учитывая невероятный JavaScript и другие динамически типизированные языки, я могу поверить, что с моим подходом что-то не так. Или это просто цена, которую вы должны заплатить?

Короче говоря:

  • Как вы подходите к проекту JavaScript (или любого другого динамического языка в этом отношении) с ~ 2000 LOC?
  • Существуют ли инструменты, которые не позволят мне совершить эти ошибки? Я попробовал поток через Facebook и JSHint, которые несколько помогают, но не ловят опечатки.
TomTom
источник
2
Хотя есть способы смягчить издержки, там есть затраты .
dcastro
29
Я бы попробовал написать вашу программу на статически типизированном языке, который компилируется в javascript, например Typescript, Scala.js или Elm.
dcastro
6
тестирование, тестирование, дополнительные тесты и отчеты о покрытии.
njzk2
7
~ 2000 LOC - небольшой проект. Это должно легко вписаться в то, что динамический язык делает легко и хорошо. Если вы боретесь с такого рода проектами, у вас есть более фундаментальная проблема с вашими навыками программирования, чем что-либо, имеющее отношение именно к динамическим языкам.
Джек Эйдли
5
@JackAidley Не согласен. OP используется, чтобы сосредоточиться на проблемах высокого уровня, а не на том, правильно ли написан идентификатор. Это навык программирования. Обеспечение правильного написания может быть выполнено помощником среднего класса и / или инструментом.
Мукахо

Ответы:

37

Говоря конкретно о JavaScript, вы могли бы вместо этого использовать TypeScript . Он предлагает некоторые вещи, на которые вы ссылаетесь. Цитирование сайта:

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

И это просто расширенный набор JS, означающий, что часть вашего существующего кода будет отлично работать с TS:

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

VinArrow
источник
11
... а TypeScript - это, по сути, Ecmascript 6.
Роберт Харви
11
Эту цитату больно. Это просто показывает, что Microsoft всегда была компанией со статическими языками, которая просто не понимает динамические языки. "Типы позволяют ... рефакторинг кода"? В самом деле? Понимает ли отдел по связям с общественностью Microsoft, что рефакторинг кода как практика был изобретен в Smalltalk (динамический язык) и существовал еще до этого в Forth (язык без типов)? Что самый первый автоматизированный инструмент рефакторинга был частью Smalltalk IDE, еще до того, как у статических языков были IDE? Что современные среды разработки Smalltalk имеют инструменты рефакторинга, по крайней мере, такие же мощные, если не больше, чем Java, C # и C ++? Да брось.
Jörg W Mittag
5
TypeScript - отличный язык сам по себе, почему вы должны пытаться продвигать его с такой ерундой?
Jörg W Mittag
29
@ Йорг Я достаточно о Smalltalk не знаю, но каждый IDE для JavaScript или Python я видел мили за то , что хороший IDE для Java или C # можно сделать. Также есть некоторые вещи, которые просто невозможно сделать на динамическом языке (некоторые из самых популярных рефакторингов на самом деле): скажем, у вас есть публичная функция foo(x) { return x.bar;}или что- то в этом роде . Поскольку информация о типе отсутствует и функция общедоступна (следовательно, вы не можете знать всех вызывающих), вы не сможете определить, следует ли переименовать bar в baz, если вы переименуете какой-то класс.
Во
10
Этот ответ говорит о том, что решение проблемы «динамических языковых ошибок» вовсе не заключается в использовании динамического языка.
bgusach
19

Есть несколько подходов, которые могут помочь:

Модульное тестирование

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

Используйте рамки

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

Предпочитаю CSS / языки высокого уровня

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

Refactor

Рефакторинг для уменьшения количества кода. Меньше кода = меньше мест, чтобы что-то пошло не так.

Повторное использование

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

Иды

Современные IDE обычно имеют хотя бы некоторую поддержку Javascript. Некоторые текстовые редакторы также поддерживают Javascript.

Робби Ди
источник
5
Хотя это верно, ваш совет применим в основном ко всем языкам программирования и в основном направлен на исправление логических ошибок, а не ошибок, возникающих в динамических языках.
edmz
1
«Ваш совет относится в основном к каждому языку программирования» . Совершенно верно - подобно тому, как переходить от механизмов хобби к полнофункциональным корпоративным решениям, что требует все большего количества ограничений, аналогично - чем больше написано Javascript, тем больше дисциплины нужно, если колеса не идут быстро оторваться. Эрик Липперт очень хорошо это описывает.
Робби Ди
4
«Предпочитаю CSS / языки высокого уровня» - я не очень понимаю, что означает этот бит по отношению к JavaScript: вы говорите, что элементы (например, анимация, возможно) перемещаются в таблицы стилей, а не в код JS? Как CSS относится к языкам высокого уровня?
anotherdave
@anotherdave Многое из того, что раньше было сферой деятельности Javascript, теперь может быть достигнуто в CSS3. Некоторые функциональные возможности также могут быть перенесены на язык более высокого уровня, который будет подвергаться более строгому контролю.
Робби Ди
4
@anotherdave Многое из того, что люди пытаются сделать с помощью JavaScript, является посторонним и неуместным. Библиотеки, предоставляющие стандартные языковые инструменты, фреймворки, предоставляющие немного больше стандартных элементов HTML, код, который воспроизводит базовые функции, такие как якоря, эмуляция MVC, стилизация, повторная реализация DOM, абстракция AJAX, рендеринг тривиальных объектов (переопределение SVG), функции поли-заполнения, которые не приносить пользу пользователю ... Вы должны минимизировать количество JS, которое вы пишете. Если вы можете сделать это без JS, сделайте это без JS.
bjb568
2

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

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

Это был эффективный инструмент для меня (помимо статических анализаторов), и, учитывая, что размер вашего проекта 2k LOC, который, на мой взгляд, не слишком велик, должен творить чудеса.

mucaho
источник
2
grepпроходит долгий путь Если вы не делаете слишком странные динамические вещи, это делает свое дело. Тем не менее, это выглядит очень ручным, если вы привыкли к IDE для статических типизированных языков.
bgusach
1

В настоящее время я занимаюсь рефакторингом нескольких тысяч строк кода в большом проекте AngularJS. Одна из самых больших проблем заключается в том, чтобы выяснить точный контракт данной функции. Иногда я заканчивал тем, что читал документацию по API, потому что элементы необработанного ответа API были назначены переменным, которые прошли через 6 уровней кода перед изменением и вернулись через еще 6 уровней кода.

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

Мой второй совет - проводить как можно больше проверок. Мы следуем стандарту AirBnB и используем eslint на всей нашей кодовой базе. Подтвердите, что мы всегда следуем стандарту. Естественно, у нас есть батарея юнит-тестов и приемочные тесты, и все коммиты должны проверяться коллегами.

Переход от текстового редактора (Sublime Text) к надлежащей IDE (WebStorm) также значительно облегчил работу с кодом в целом. WebStorm будет использовать JSDoc, чтобы давать подсказки об ожидаемых типах параметров и сообщать об ошибке, если вы указали неправильный тип или неверное использование возвращаемого значения.

В JavaScript новые функции, такие как символы и методы получения / установки, могут помочь обеспечить определенный уровень качества путем добавления утверждений к назначению переменной (например, убедитесь, что целое число находится в пределах диапазона, или что объект данных имеет определенные атрибуты).

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

Николас Булиан
источник
0

Мой ответ на вопрос «Как вы подходите к проекту JavaScript (или любого другого динамического языка в этом отношении) с ~ 2000 LOC?»

Я разрабатываю приложения в форме PDF. Я подхожу к своему проекту разработки программного обеспечения для JavaScript (независимо от размера исходного кода), используя сетевые элементы и аннотации Петри. Метод не привязан к какой-либо конкретной технологии языка программирования. Таким образом, он может быть использован для других «языков программирования».

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

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

Я также использую Eval. Это может значительно уменьшить размер исходного кода. Из-за проблем с производительностью я использую eval в начале или в части инициализации моего приложения; Я никогда не использую его в «логике времени выполнения» - это еще одно соглашение по кодированию, которому я следую.

Джон Фредерик Чионгло
источник