LINUX.ORG.RU

JavaScript надежность


2

10

Добрый вечер! Увидел тему про Linux на JS в разделе. Видел PDF.js и возникает у меня следующий вопрос. Сколько не пытался писать на JS (обычно пишу на Java и еще иногда приходится на C) всегда сталкивался с проблемой возникновения большого количества ошибок в рантайме из-за динамической типизации. Как людям удается создавать приложения такой сложности на JS?

У меня получалось быстро и относительно без багов написать только с GWT, но это по сути это Java. Но мне довелось читать много негативных отзывов по GWT, что дескать просто на JavaScript проще.

Почему проще? Как вы отлаживаете большие приложения на JS? Как обеспечиваете модульность и при этом производительность?

Речь сейчас именно о сложных скриптах, а не простых интерфейсиках с jQuery UI.

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

Перемещено tazhate из development

★★

Последнее исправление: olegk (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Если бы покрытие было 100%, этих ошибок не было бы.

С чего вдруг? Чтобы их не было вообще нужно покрытие путей, и тут 100% действительно никогда нету.

Всё ты понял.

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

anonymous
()
Ответ на: комментарий от quasimoto

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

Так в чем проблема сделать ее макросом, который раскрывается в ф-ю в не-head позиции?

Всё это есть, если посмотреть в CLHS, то определения соответствующих стадий можно найти (другое дело, что они циклически замкнуты в рамках одного рантайма).

Нет, не в этом проблема. Проблема в том, что все эти «времена» определяются как «Х - время выполнения функции Y». На месте Y ридер, экспандер, компилятор и т.д.., причем семантика указанных ф-й обычно никак не определена (или определяется как «ф-я Y - то, что вызывается во время Х» - сепульки, короче), а моменты их вызова специфицированы крайне скупо или не специфицированы вовсе. Ну оно и понятно - ведь мы всегда может любую из этих ф-й переопределить и вызвать сами, руками. Соответственно, если бы указанные вещи были и специфициованы, то полагаться на эти спецификации мы бы все равно не могли.

(ещё скажи, что машкода тоже нет)

Так я это уже говорил. Если есть ф-я Х и есть машкод Y, то Y - машкод данной функции тогда и только тогда, когда интерпретация машкода вычислительным устройством совпадает с интерпретацией исходного кода ф-и интерпретатором (то есть семантика не меняется при замене интерпретатора на компилятор). Для общелиспа это неверно - начиная с размытости понятия «исходного кода» (нету никакого кода, есть произвольный граф объектов, загруженный в образ, который НЕ является текстом на каком-бы то ни было языке), заканчивая тем, что семантика кода может меняться весьма драматично в зависимости от того, был ли код загружен через load, скомпилирован, находился ли в топ-левел или локальном контексте и т.д., ну а если уж про eval-when вспомнить - тут сами общелисперы уже давным-давно все в красках рассказали.

anonymous
()

Динамическая типизация это не торт. Как пишется хорошее большое приложение на js? Ну..

Оно пишется только если руки у людей не из жопы, сам язык не предлагает надежных, не обходимых, механизмов антиотстрела ноги. Проблема в том, что часто пишут на js как раз Java, С программисты, но не люди прочитавшие хотя бы javascript ninja. Хоть один паттерн бы осилили, а так..

Впрочем, недоделаная статическая типизация java, это лишь немногим лучше.

Boui
()
Ответ на: комментарий от tailgunner

Ну ну.

Если бы покрытие было 100%, этих ошибок не было бы.

Покрытие 100% конечно может быть (сомнительно в больших проектах, даже нереально, хотя может это мне так не везло), но где набрать людей, которые напишут такие тесты, которые помогут реально выявить ошибку? Тесты разные бывают, не мне говорить насколько покрытие обманчиво в роли показателя надежности.

Boui
()
Ответ на: Ну ну. от Boui

Покрытие 100% конечно может быть

Теоретически.

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

И сколько сил они потратят на написание этих тестов.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

В большинстве проектов, если девелопер запустит integration тесты, то 20% из них упадет. И исправлять надо будет не код - а тесты. Тесты - это еще и поддержка тестов. Если ниче не упадет при компиляции(привет динамическим языкам программирования), то без тестов грустно, а с некоторыми тестами еще грустнее. Так и получается тупик в развитии проекта. Короче мораль - не пишите много логики на js, а если пишете - придется страдать

Boui
()
Ответ на: комментарий от Boui

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

Но практика показывает обратное - идет время, компьютеры становятся быстрее, производительность ЯП (единственный реальный профит от статической типизации) уже не так важна, как следствие, динамические языки используются все чаще и чаще. Бороться с ошибками позволяет низкая связность, правильная декомпозиция, избегание сложностей, статическая типизация мешает всем этим аспектам. Так что рано или поздно статика останется уделом маргиналов (редкие высоконадежные системы, которые будут писаться на ЯП с зависимыми типами), а все остальное будет писаться на няшной динамике, которая, в отличии от статики, упрощает отладку и избегание ошибок, а не усложняет ее.

anonymous
()
Ответ на: комментарий от anonymous

Ты можешь привести пример небольшой практической задачи, которая не решается (или плохо решается) на статически типизированном языке и аналогичное решение на динамическом? С кодом.

encyrtid ★★★★★
()
Ответ на: комментарий от encyrtid

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

anonymous
()
Ответ на: комментарий от anonymous

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

Т.е кроме невозможности сделать лисповый flatten, внятных претензий к статической типизации мы не услышим?

encyrtid ★★★★★
()
Ответ на: комментарий от encyrtid

«ненужное усложнение» и «ограничение выразительности языка» - это НЕ внятные претензии? Можно тогда увидеть какой-нибудь пример внятной претензии? Ну, например, выскажите какую-нибудь внятную претензию к брейнфаку.

anonymous
()
Ответ на: комментарий от anonymous

Я хочу 2 куска кода: 1-й на статически типизированном языке с комментариями почему все плохо, 2-й на динамическом языке с комментариями почему все хорошо. Адепты динамических языков всегда приводят примеры абстрактных коней в вакууме, я хочу видеть наглядный пример преимущества динамики.

encyrtid ★★★★★
()
Ответ на: комментарий от encyrtid

Внятная претензия к брейнфаку будет или нет?

anonymous
()
Ответ на: комментарий от anonymous

«ненужное усложнение» и «ограничение выразительности языка» - это НЕ внятные претензии?

Без кода - да.

encyrtid ★★★★★
()
Ответ на: комментарий от encyrtid

Я все еще жду внятную претензию к брейнфаку. С кодом.

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

anonymous
()
Ответ на: комментарий от anonymous

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

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

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

anonymous
()
Ответ на: комментарий от anonymous

Если статикодебилам можно пиздеть всякую ничем не подкрепленную хуету, то почему нельзя мне?

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

anonymous
()
Ответ на: комментарий от anonymous

Давайте постараемся говорить меньше слов. Например, реализация чистой функции, которая принимает параметры List[A], а возвращает А.. Что оно может делать вообще? Чтоб ты не задерживался, я сразу скажу - ничего оно не может делать. Это значит, что просто оценив типы функции, я сразу понимаю что она делает, и чего она не может делать. Я захожу в код на javascript некто назвал параметры функции a и b, а саму функцию f123 и что теперь можно понять?

Boui
()
Ответ на: комментарий от Boui

Например, реализация чистой функции, которая принимает параметры List[A], а возвращает А.. Что оно может делать вообще?

Да все что угодно, слишком много вариантов.

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

Это кто тебе такое сказал? Наебали тебя, братюнь.

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

Опять статикоказки пошли.

Я захожу в код на javascript некто назвал параметры функции a и b, а саму функцию f123 и что теперь можно понять?

Ничего. Точно так же как и в случае со статикой. Надо читать реализацию.

anonymous
()
Ответ на: комментарий от Boui

Ах, да, вот и замечательный пример говенности статики - идиоты думают, что что-то там можно узнать из типа, а потом пишут ф-ю f123 с аргументами a и b. Про документацию и упоминать не стоит.

anonymous
()
Ответ на: комментарий от Boui

Например, реализация чистой функции, которая принимает параметры List[A], а возвращает А.. Что оно может делать вообще? Чтоб ты не задерживался, я сразу скажу - ничего оно не может делать.

1. head
2. head . tail
3. head . tail . tail
4. head . tail . tail . tail
5. ... (счетное множество)
dave ★★★★★
()

Тут что серьёзно кто-то обсуждает язык для рисования окошек в браузере?

anonymous
()
Ответ на: комментарий от anonymous

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

JFreeM ★★★☆
()
Ответ на: комментарий от dave

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

2anonymous Давай хоть один, с учетом отсутствия исключительных ситуаций

Boui
()
Ответ на: комментарий от Boui

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

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

dave ★★★★★
()
Ответ на: комментарий от encyrtid

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

Tark ★★
()
Ответ на: комментарий от anonymous

Так в чем проблема сделать ее макросом, который раскрывается в ф-ю в не-head позиции?

А как это будет в CL? defmacro для head и define-symbol-macro для не-head? Всё равно, по смыслу это должна быть функция (например, чтобы trace можно было сделать, чтобы в stacktrace была, чтобы можно было передавать символ (define-symbol-macro сразу в lambda раскроется и та будет передаваться как function) и сделать символу #' (т.е. (function symbol))).

Относительно всего остального - я всё-таки предполагаю разумное использование, то есть без переписывания компилятора и пакета CL (на самом деле, они locked в SBCL - нужно сначала разрешить переписывание), даже без явных вызовов eval, macroexpand и т.п.

quasimoto ★★★★
()
Ответ на: комментарий от Tark

Вы чето не очень поняли, что вам говорят? Я говорю повесишься писать 10 тыс строк и тестировать их. Да, можно без типов, но все зависит от задачи. Представь у тебя сервис - а там надо распарсить, что пришло от клиента. Варианты - А, В, С. Паттерн матчинг по типу и поехали(в статике), а как по-нормальному в js? Надо попробовать запросить поле - не вышло - exception - дальше... Или поле с типом будет? А неожиданные исключительные ситуации... всего и не упомнишь

Boui
()
Ответ на: комментарий от anonymous

Да все что угодно, слишком много вариантов.

Не, можно написать Default a => [a] -> a, то есть семейство функций [InhabitedType] -> InhabitedType, но написать _функцию_ [a] -> a нельзя.

quasimoto ★★★★
()
Ответ на: комментарий от Boui

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

Tark ★★
()
Ответ на: комментарий от Boui

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

Tark ★★
()
Ответ на: комментарий от Tark

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

В playframework для этого есть Forms - несколько более сложно чем паттерн-матчинг, но он тоже может использоваться в verifying / fold.

quasimoto ★★★★
()
Ответ на: комментарий от tailgunner

Скачал, поглядел примеры, первые пару минут хотелось выколоть себе глаза, но потом ничего, привык. Нашел где делать много вариантов в одном поле, но так и не нашел где там есть не обязательные поля. Не делать же на каждый вариант собственный тип? Хотя в принципе годная вещь.
Просто например в некоторых АПИ пользователь может дать доступ к некоторым полям, а может не дать. Поэтому поле вроде как нужное и используемое, а вроде как его может и не быть. Как такие ситуации обрабатывать с помощью паттерн маттчинга?

Tark ★★
()
Ответ на: комментарий от Tark

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

Я знаю о ДОМ чуть более, чем ничего, так что твоего вопроса просто не понял :)

tailgunner ★★★★★
()
Ответ на: комментарий от quasimoto

Не вижу особой разницы между подобным Forms и реализацией валидаторов в остальных фреймворках? Хотя выглядит конечно довольно кратко и удобно.

Tark ★★
()
Ответ на: комментарий от tailgunner

Это не DOM, просто юзер может разрешить апи возвращать возраст, а может и не разрешить. Если таких полей больше половины, есть ли смысл использовать паттерн матчинг?
Хотя я вообще не понимаю смысла паттерн матчинга для парсинга того, что пришло от клиента.

Tark ★★
()
Ответ на: комментарий от Tark

Это не DOM, просто юзер может разрешить апи возвращать возраст, а может и не разрешить

Мм... со ссылки:

match e with
  name[val n], addr[val a], tel[val t] -> (* телефон известен *)
| name[val n], addr[val a] -> (* телефон неизвестен *)

Хотя я вообще не понимаю смысла паттерн матчинга для парсинга того, что пришло от клиента.

Смысл if ты понимаешь? Смысл регэкспов? Так вот, паттерн матчинг - это if с множеством альтернатив, который использует регэкспы над структурами данных.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Нашел где делать много вариантов в одном поле, но так и не нашел где там есть не обязательные поля. Не делать же на каждый вариант собственный тип?
Если таких полей больше половины, есть ли смысл использовать паттерн матчинг?

Tark ★★
()
Ответ на: комментарий от Tark

Нашел где делать много вариантов в одном поле, но так и не нашел где там есть не обязательные поля

Что непонятно в словах «optional Tel» во фразе:

«The type (Name,Addr,Tel?)* means zero or more repetitions of the sequence of a Name, an Addr, and an optional Tel»

?

Если таких полей больше половины, есть ли смысл использовать паттерн матчинг?

«Больше половины» - это 2 из 3? Имеет. 20 из 30? Может быть.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

«The type (Name,Addr,Tel?)* means zero or more repetitions of the sequence of a Name, an Addr, and an optional Tel»

Да, ступил. Думал, что нужно обязательно конструкцию с match писать, чтобы обрабатывать.

«Больше половины» - это 2 из 3? Имеет. 20 из 30? Может быть.

20 из 30 естественно.

Tark ★★
()
Ответ на: комментарий от Tark

20 из 30 естественно.

Всё это поля одного объекта и могут отсуствовать/присуствовать в любой комбинации? Тогда мы имеем случай сильно кривого дизайна, который никаким способом красиво не обработаешь.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

Tark ★★
()
Ответ на: комментарий от Tark

А вот другой случай, для ускорения работы апи возвращает только те поля, которые запрашиваются, либо стандартный набор полей

Если известно, что все элементы присуствуют, зачем паттерн-матчинг?

tailgunner ★★★★★
()
Ответ на: комментарий от Tark

Там результатом этого валидатора является tuple, который, при сложных формах, предполагает разбор в PM. При более простых формах можно этот tuple отразить на свой тип - опциональные параметры кодируются как Option, PM по нему тоже естественен (и даже необходим). Тут есть пара примеров.

quasimoto ★★★★
()
Ответ на: комментарий от Tark

Ну представь что у тебя callback ajax запроса. Но у тебя не тру REST, для тру реста у тебя не хватило времени. И в зависимости от того что пришло от серверсайда тебе надо осуществить разные действия. А чтобы тебе было веселее - у тебя 5 видов ошибок, которые могут быть возвращены в ответ на запрос который ты осуществляешь. И все поля у них одинаковые, только тип разный да сообщение об ошибке. Обработай

Boui
()
Ответ на: комментарий от Boui

Что сложного в том, чтобы в ответ давать {'status' => 'ok'|'error', 'details' => {имя ошибки либо тип объекта}?
Да и в любом случае, если тип разный и указан, то чем массив из функций обработчиков не угодил?

Tark ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.