Как вы используете утку, набрав в javascript, не всегда проверяя свойства и методы?


11

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

if(myObj.hasSomeProperty())

или же

if(myObj.hasSomeMethod())

или же

if(isNumber(myParam))

и т.п.

Это действительно безобразно для меня. Я пришел из C # фона и считаю, что определенные интерфейсы намного лучше.

Мне интересно, если я неправильно пытаюсь применить стратегии, которые эффективны в статически типизированных языках, и есть ли лучший способ сделать это в JavaScript?

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


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

Где это может помочь сделать эти проверки, чтобы удостовериться, что типы соответствуют необходимым требованиям интерфейса (например, проверить, есть ли у них требуемые методы), находится в ваших самых центральных и широко используемых функциях (с нестабильностью = 0 с метрика эфферентная / афферентная связь, которую обеспечивает Мартин). Это должно быть довольно маленькая цель. Как правило, существует множество одноразовых локальных функций, которые изолированы по объему, и им, вероятно, не нужен такой полный набор проверок во время выполнения. Они не накапливают много сложности.

Переключитесь на Type Script. Он по-прежнему типизирован по типу утки, но поддерживает статическую типизацию для обнаружения множества ошибок во время компиляции.
CodesInChaos

2
Вы столкнулись с одной из самых больших проблем, связанных с типизацией уток: ее сила проистекает из ее слабости. Если вы хотите сделать объектно-ориентированный JavaScript, вам просто нужно смириться с ошибками времени выполнения и надеяться, что ваши модульные тесты обнаружат их вскоре после их создания :-(
Росс Паттерсон,

@RossPatterson Проблема OPs связана с динамической типизацией, а не с утиной. TypeScript и Go оба написаны по типу утки, но позволяют избежать проблем ОП. Проблема с типизацией утки - другая, а именно: у вас могут быть участники, которые сдают тест на утку, но не выполняют ожидаемый контракт.
CodesInChaos

Ответы:


11

Как вы используете утку, набрав в javascript, не всегда проверяя свойства и методы?

Просто: не всегда проверяйте свойства и методы.

В Ruby то, что вы называете, называется "типизацией курицы". На языке динамического типа «утка» вы просто верите, что вызывающая сторона передает вам подходящий объект. Работа вызывающего абонента состоит в том, чтобы соблюдать его часть контракта.

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

Вы путаете несколько ортогональных осей печатания здесь. Различают четыре ортогональные оси набора текста:

  • Когда : динамическая типизация (типы не известны и проверяются до времени выполнения) или статическая типизация (типы известны и проверяются до времени выполнения)
  • Что : типизация утки (типы основаны на поведении ), структурная типизация (типы основаны на структуре ) и номинальная типизация (типы основаны на имени )
  • Ты их видишь? явная типизация (типы должны быть явно аннотированы) против неявной типизации (типы выводятся)
  • строгая типизация против слабой типизации - вы могли заметить, что я не дал этому броскому заголовку или объяснению в скобках, потому что, в отличие от семи терминов, приведенных выше, каждый из которых имеет одно общепринятое точное определение, эти два термина иметь около дюжины полу-широко используемых расплывчатых определений, которые противоречат друг другу; в идеале вам следует избегать этих терминов в целом, и если вы должны их использовать, сначала точно определите их

Поскольку вы упомянули C #: он в основном статически типизирован, но поддерживает динамическую типизацию через тип dynamic, он в основном номинально типизирован, но анонимные типы используют структурную типизацию, и синтаксические паттерны (такие как синтаксис понимания запросов LINQ) можно считать либо уткой типизированный или структурно типизированный, он в основном явным образом типизирован, но поддерживает неявную типизацию для аргументов универсального типа и локальных переменных (хотя регистр локальной переменной довольно странный по сравнению с большинством других языков, потому что вы не можете просто пропустить тип, вместо этого вы должны дать ему явный псевдотипvarдругими словами, если вы хотите неявный тип, вы должны явно сказать это). Независимо от того, является ли C # строго или слабо типизированным, зависит от того, какое определение двух терминов вы используете, однако обратите внимание, что в C # может быть много ошибок типов времени выполнения, особенно из-за небезопасной ковариации массива.

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

Отладка не является простым навыком для изучения. Однако существуют методы, облегчающие отладку, например, Saff Squeeze - это метод, описанный Кентом Беком, который использует тесты и рефакторинг для отладки:

Хит их высокий, Хит их низкий :

Регрессионное тестирование и сжатие Saff

Кент Бек, Институт трех рек

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


Эта ссылка «Хай-Эм-Хай-Эм-Эми-Лоу» получает для меня http 500 с сообщением «Страница больше недоступна» в качестве ориентированного на человека сообщения.
Joshp

Домен treeriversinstitute.org, похоже, был заброшен.
Барт ван Инген Шенау

Ах, черт. И это даже не архивируется на WayBack Machine .
Йорг Миттаг

Как звонящий должен соблюдать свою сторону контракта? Кажется, что нет способа сообщить (в коде), какими должны быть параметры. Каждая функция имеет вид функции fname (objParam, objParam, ...). Означает ли это, что языки, такие как javascript, полностью зависят от внешней документации для передачи информации об использовании?
Легион

@Legion: документация, правильное наименование, здравый смысл, тесты в качестве поведенческих спецификаций, чтение исходного кода, вы называете его. Обратите внимание, что это на самом деле мало чем отличается от систем более слабых типов, таких как C # или Java: например, значение возвращаемого значения IComparer<T>.Compare(T, T)ясно только из документации, а не типа. И где в типе java.util.Collections.binarySearch(java.util.List<T>)сказано, что ...
Йорг Миттаг

1

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

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

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

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

Если вы похожи на меня, когда я писал в основном на статически типизированных языках, перед тестированием я писал большие блоки кода, и у меня не было практики отследить, откуда оно взято. Программирование на языке, таком как javascript, отличается, вы должны использовать разные навыки. Я подозреваю, что подобное программирование кажется намного сложнее, потому что это не те навыки, которые вы развили, работая на других языках, таких как C #.

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


0

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

  • Вместо того, чтобы if(myObj.hasSomeProperty())вы могли использовать if( myobj.prop !== undefined ). Это, кстати, будет работать только в нестрогом режиме, в строгом режиме, который вам придется использовать if( typeof myobj.prop !== 'undefined' ).

  • Вы можете разгрузить некоторые проверки типов в отдельные валидаторы. Преимущество этого заключается в возможности пропустить проверку после того, как интерфейсы станут зрелыми, например if( is_valid( myobject )), где is_validначинается с if( !DEBUG ) return true;.

  • Иногда имеет смысл клонировать входные данные в каноническую форму, и в этом случае вы можете собрать различные объекты проверки в функцию / объект клонирования. Для exmaple, в my_data = Data( myobj, otherstuff )к Dataконструктору может удобно работать все различные валидации в центральном месте.

  • Вы можете использовать некоторую библиотеку, которая (при снижении производительности) упростит проверку вашего типа во что-то более элегантное. Даже если вы не пойдете этим путем в долгосрочной перспективе, вам может быть удобно, чтобы вы плавно перешли в свой собственный стиль. Некоторые примеры включают xtype.js , тип-чек , validator.js и т.д.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.