Як ви використовуєте набір качок у javascript, не перевіряючи завжди властивості та методи?


11

Я знаю, що JavaScript використовує набір качок, і спочатку я думав, що це полегшить поліморфізм порівняно з сильно набраними мовами, такими як C #. Але тепер мої функції, які беруть аргументи, вписані такими, як:

if(myObj.hasSomeProperty())

або

if(myObj.hasSomeMethod())

або

if(isNumber(myParam))

тощо.

Це справді некрасиво для мене. Я надходжу з фону C # і я вважаю, що визначені інтерфейси є набагато кращими.

Мені цікаво, чи я неправильно намагаюся застосувати стратегії, ефективні в мовах статичного типу, і є якийсь кращий спосіб зробити це в JavaScript?

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


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

Там, де це може допомогти зробити ці перевірки, щоб переконатися, що типи відповідають необхідним інтерфейсним вимогам (перевірка, чи є у них потрібні методи, наприклад), у ваших найбільш центральних та широко використовуваних функціях (тих, у яких нестабільність = 0, метрика еферентного / аферентного зв’язку, яку надає Мартін). Це має бути досить маленькою ціллю. Зазвичай існує велика кількість одноразових локальних функцій, які є відокремленими за обсягом - їм, ймовірно, не потрібен такий всебічний набір перевірок виконання. Вони не накопичують великої складності.

Переключитися на тип сценарію. Це ще качка набрана, але підтримує статичний набір тексту для виявлення багатьох помилок під час компіляції.
CodesInChaos

2
Ви зіткнулися з найбільшою проблемою введення качки: її сила випливає із слабкості. Якщо ви хочете робити об’єктно-орієнтований JavaScript, вам просто доведеться жити з помилками під час запуску, і сподіваюся, що ваші тестові одиниці знайдуть їх незабаром після їх створення :-(
Росс Паттерсон

@RossPatterson Проблема з ОП полягає в динамічному наборі тексту, а не при натисканні качок. TypeScript і Go обидва набрані качка, але уникнути проблеми ОП. Проблема з набором качок є іншою, а саме тим, що ви можете мати членів, які проходять тест на качку, але не виконують очікуваний вами контракт.
CodesInChaos

Відповіді:


11

Як ви використовуєте набір качок у javascript, не перевіряючи завжди властивості та методи?

Просто: не завжди перевіряйте властивості та методи.

У Рубі те, що ти називаєш, називається "курячий набір". На мові, динамічно набраній качкою, ви просто довіряєте, що абонент передає вам відповідний об’єкт. Завдання, що телефонує, - поважати його сторону договору.

Я знаю, що JavaScript використовує набір качок, і спочатку я думав, що це полегшить поліморфізм порівняно з сильно набраними мовами, такими як C #.

Тут ви плутаєте кілька ортогональних осей введення тексту. Існує чотири ортогональних осі введення тексту:

  • Коли : динамічне введення тексту (типи невідомі та перевірені до виконання) та статичне введення (типи відомі та перевірені перед виконанням)
  • Що : типи качок (типи засновані на поведінці ), структурна типізація (типи засновані на структурі ) та номінальна типізація (типи засновані на імені )
  • Ви їх можете бачити? явне введення тексту (типи мають бути явно анотованими) проти неявного введення тексту (типи виводяться)
  • сильне введення та слабке введення тексту - ви, можливо, помітили, що я не дав цьому влучному заголовку чи поясненню в круглих дужках, це тому, що на відміну від семи термінів, які мають вище, кожен має єдине загальновизнане точне визначення, ці два терміни мають близько десятка напіввживаних розпливчастих визначень, які суперечать один одному; в ідеалі вам слід взагалі уникати цих термінів, і якщо ви повинні їх використовувати, то в першу чергу їх точно визначте

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

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

Налагодження - це не простий навик навчання. Однак існують методи, які спрощують налагодження, наприклад, Saff Squeeze - це техніка, описана Кентом Беком, яка використовує тести та рефакторинг для налагодження:

Удари їх високо, удари їх низько :

Регресійне тестування та видавлювання шафу

Кент Бек, Інститут трьох річок

Анотація: Щоб ефективно ізолювати дефект, починайте з тесту на системному рівні та поступово встромляйте та підрізайте, поки у вас є найменший можливий тест, який демонструє дефект.


Це звернення em high hit em low link отримує для мене http 500, "Сторінка більше не доступна" як повідомлення, орієнтоване на людину.
joshp

Здається, домен threeriversinstitute.org був покинутий.
Барт ван Інген Шенау

Ах, чорт. І навіть не архівовано на машині WayBack .
Йорг W Міттаг

Як абонент повинен шанувати свою сторону договору? Схоже, немає способу повідомляти (в коді), якими мають бути параметри. Кожна функція має назви функції fname (objParam, objParam, ...). Чи означає це, що мови, як Javascript, повністю залежать від зовнішньої документації для використання зв'язку?
Легіон

@Legion: документація, добре називання, здоровий глузд, тести як специфікації поведінки, зчитування вихідного коду, ви його називаєте. Зауважте, що це насправді мало чим відрізняється від систем слабшого типу, таких як C # або Java: Наприклад, значення поверненого значення IComparer<T>.Compare(T, T)зрозуміло лише з документації, а не типу. І де у типі java.util.Collections.binarySearch(java.util.List<T>)це написано, що…
Jörg W Mittag

1

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

Дійсно, типова практика не перевіряти. І так, це означає, що ви отримаєте помилки javascript, які повідомляються в іншому місці від фактичної проблеми. Але на практиці я не вважаю це великою проблемою.

Під час роботи в JavaScript я постійно тестую те, що пишу. У більшості кодів у мене є одиничні тести, які автоматично запускаються кожного разу, коли я зберігаю свій редактор. Коли щось несподівано піде не так, я знаю майже одразу. У мене дуже мала область коду, в якій я, можливо, помилився, оскільки майже завжди останнє, чого я торкнувся, має помилку.

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

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

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


0

Я думаю, що ти робиш правильно, потрібно просто знайти стиль, який буде більш приємний для твого ока. Ось кілька ідей:

  • Замість if(myObj.hasSomeProperty())вас можна було б використовувати if( myobj.prop !== undefined ). Це, BTW працюватиме лише в не строгому режимі, у суворому режимі, який вам доведеться використовувати 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.