Комментарии 172
И там очень странные баги: если взять единицу как цифру и добавить к единице как строке и потом отнять единицу, ты получишь совершенно неожиданный результат.
После этого не читал, очевидно что это исповедь идиота.
Подозреваю, что человек говорит об отсутствии вменяемых средств контроля над приходящим в параметры функции. В итоге код рассчитан на одно, приходит ему другое и получается "совершенно неожиданный результат". Это подтверждается упоминанием Typescript ниже по тексту.
— Лисп — убейте, слишком много скобок
— PHP — убейте, от знаков доллара рябит в глазах
— ASM — убейте, классов нет
Применительно к ситуации: не умеешь / не хочешь контролировать то, что тебе приходит на вход — сам виноват, винить в этом «кривость» языка — неправильно.
А то получается какая то подростковая логика вроде как РЭП — это кал, а почему? А потому что он мне не нравится и слушаю я Курта Кобэйна.
Ну так работа с памятью в С — это важный его атрибут, как языка, ориентированного на высокую производительность.Именно! Это не баг, не странный баг, не недокументированная особенность — это просто то как оно есть, а вот вопрос нравится это вам или нет — это уже дело сугубо личное. Не думаю, что человека, который позиционирует себя как разработчика на C, при приеме на работу оценили бы по достоинству если бы он назвал работу с памятью — лишним не нужным никому геммороем.
А отсутствие type-checking в JavaScript какую пользу приносит? Дело ведь не в том, что я хочу type-checking, дело в том, что я мог бы безболезненно его получить ( как минимум я не вижу препятствий ). По мне так это просто самый лютый факап разработчиков языка))
Изначально ES задумывался как интерпретируемый язык программирования (не берем в учет то как его обрабатывают современные JS движки c их JIT'ами и оптимизациями), так вот при такой схеме, иногда бывает весьма сложно (если не невозможно) понять какого конкретно типа значение является операндом того же арифметического выражения. 1 + '1' это очень простой пример, возьмем ситуацию когда вместо литералов у нас переменные:
var left = 1;
var right = '1';
var result = left + right;
Тут нужно уже прогнать весь код через проверку типов для того чтобы понять что за тип у left и right, для того чтобы в итоге проверить существует ли возможность применить оператор "+" к данным типам данных. А что если одна из переменных объявлена за пределами модуля в котором выполняется выражение? Прогнать и этот модуль, а что если этот модуль загружен извне? Загрузить его и прогнать? А что если этот модуль нами не управляется? Благодаря всем этим «а что» и «а если», мы получаем существенный удар по производительности (если говорим о проверке типов в рантайме), если же такую проверку производить до рантайма, то нам нужно скачивать вообще все что имеет отношение к нашему приложению, что в свою очередь не есть плохо или хорошо, просто это уже превращается в другой язык программирования.
Вот это вот хуже всего, на самом деле, потому что это очень сложно сделать правильно.
Ну вы то надеюсь поможете сделать правильно, если понадобится?
У меня есть впечатление, что правильно — это через зависимый тип-сумму вида (a: Type ** a)
Зачем здесь зависимый тип? :hz:
С хошь пользуйся хошь не пользуйся проблема в границах между типизированным и нетипизированным кодом, не совсем понятно, что там делать.
В Racket пытались, но там очень мощная система контрактов, которая позволяет автоматически заменять аннотации типов в типизированном коде при импорте в нетипизированный на контракты, с-но soundness остается просто на уровне рантайма и по крайней мере мы получаем блейм контракта по типу в том месте, где типы не совпали, а не черт знает где, что сохраняет корректность в итоге. Только для этого надо уметь делать контракты на ФВП и на параметрически полиморфные ф-и, чего я больше-то нигде и не видел, плюс в определенных случаях это приводит к существенной деградации производительности.
Альтернативный вариант — просто тупо типы забывать, но в этом случае гарантированно корректный код перестает быть корректным и зашкваривается об границу.
Потом, в принципе, никто не мешает заматчить на первый (или даже на второй) элемент пары, кроме криво реализованной проверки на parametricity в идрисе.
А чем это отличается от:
const lst1 = [42, 'meh'];
const lst2 = ['wuh', 13.0];
const lst3 = [42, 13.0];
const lst4 = ['meh', 'wuh'];
const zip = <A, B>(l1: A[], l2: B[]) => l1.map((a, b) => [a, l2[b]] as [A, B]);
const res = zip(lst1, lst2); // [string | number, string | number]
const res2 = zip(lst3, lst4); // [number, string][]
const res3 = res2.map(x => x[1]); // string[]
?
Тем, что вы не сможете работать с первым элементом lst1 так, будто это число, не проверив, что это число. И тайпчекер статически гарантирует наличие этой проверки.
Ну в примере выше то же самое. В третьем кейзе (res3) статически понятно что первый элемент — точно строка, а в первом — мы этого не знаем, с-но надо поставить на тип string | number гвард:
const x = res[0][0];
x.length; // error
if (typeof x === 'string') {
x.length; // ok
}
Тайпчекер напомнит. Вторая строчка не компилируется без гварда, ошибка типов там, т.к. у типа number нету свойства length.
Так, стоп, а это какой язык? Я чё-т думал, что всё ещё JS.
Typescript, так что почти верно :)
Если там есть статические типы, то какой тип в общем виде выводится у списка? Variant из всех имеющихся в нём?
у res1 будет тип [string | number, string | number][].
A[] — список из А,
[A, B] — пара из типов А и В (списки из конкретного конечного числа элементов вместо таплов выступают)
string | number — объединение (неразмеченное!) типов А и В.
С-но, получаем список из пар, элементы которых — строка или число.
Что будет, если я добавлю туда ещё какой-нибудь объект типа person?
будет [string | number | Person, string | number | Person][].
Списки и таплы там базовые типы (ну, стоит оговориться сразу, что списков в тс нет, т.к. тс — это просто js с типами, с-но список там это тот же массив, он же хеш, он же Гога, он же Жора...), [A, B] — подтип для [A | B][].
rest generics пока не завезли, так что руками такой полиморфный конс написать не выйдет, можно сказать что для каждого конечного числа там свой предефайненный конс.
Как будет выглядеть функция, которая считывает список из произвольных типов с диска или по сети?
readFileSync возвращает string либо Buffer (в зависимости от перегрузки), Buffer в свою очередь имеет ф-и для чтения чисел разного формата, наследует Uint8Array, и, кроме прочего:
toJSON(): { type: 'Buffer', data: any[] };
с-но тут зашквар, потому что any — это тип который assignable to и assignable from для любого типа. То есть универсальный подтип и супертип. С-но, на нем можно вызывать любые операции без гвардов (нужен этот тип
в основном для использования библиотек js, окторые не имеют нормальных тайпингов, просто можно поставить классу any и вызывать на нем любые методы, которые будут возвращать, в свою очередь, тоже any).
Правда, сейчас (в 3.0) добавили тип unknown — это классический Top и по идее типизировать такие вещи надо будет через него.
Ну вот в этом и разница. С List Dyna не нужно никаких полиморфных консов, все такие списки имеют один и тот же тип.
List Dyna этот в данном случае тот же unknown[], так что разницы нет. Просто тайпчекер сразу сузил тип с any[] до [(number | string), (number | string)][].
Не забывайте, что при сабтапинге тип любого значения не только самый узкий, но и любой его надтип.
А так-то я и на С++ вам с std::variant могу наваять, чтобы проверки обязательно были нужны
Не получится, т.к. в сишке гвардов нет. То есть вам компилятор не гарантирует, что в вашем variant останется то что нужно, а не бяка, и не сузить тип когда гвард есть, а в этом ведь с-но вся суть.
Ух, наркомания какая.
Ну тут надо понимать, что, в отличии от "классических" нетривиальных систем типов (вроде какого-нибудь хаскеля), которые появлялись по принципу: "у нас тут есть какие-то теоретические соображения, давайте их реализуем" тут путь противоположный: "у нас есть конкретная практическая задача, которая состоит в типизации существующих идиом и миллионов строк кода с их использованием, давайте придумаем какую-нибудь теорию для этого". С-но и система типов в итоге получается несколько необычной. С другой стороны — одна весьма выразительна с формальной точки зрения (из условно мейнстримных языков, наверное, только scala на том же уровне) и при этом все фичи, что есть очень удобно использовать на практике, т.к. они появились из-за попытки типизации кода, который писался на практике.
Например, я выше приводил пример с проверкой того, что при запросе на сервер мы не попросим несуществующих полей — соответствующий инвариант на типах фиксируется одной строчкой. А есть эта возможность в типах благодаря тому, что надо было умять типизировать код вида getProperty(object, "propertyName").
Именно! Это и есть полностью динамический список, в этом и смысл!
При этом, в очень жёстко типизированном языке.
Ну вот тайпскрипт — жестко типизированный язык (если any убрать, но в теории с-но any и нет, это вполне конкретный костыль для вполне конкретных кейзов, по-этому можно его не учитывать), в нем это все есть и не требует всякого рокетсаенса в виде зависимых типов :)
Вы просто про зт в качестве решения упомянули — и я привел это дело все в качестве примера того, что зт тут явный оверхед и из пушки по воробьям. Вообще говоря, для зт трудно привести пример задач, где они не оверхед — это слишком универсальный инструмент, и потому крайней неудобный.
Это удобно до первой неконсистентности.
Во-первых, все, что выше описано — полностью консистентно, в смысле существования soundness варианта (именно такой вариант реализован в Racket, ну оно и понятно, академический язык все же).
Во-вторых, в случае тайпскрипта консистентность намеренно нарушена в некоторых случаях (наличие any и косяки с вариантностью) — и как раз для удобства. Так что в общем случае это консистентность противоречит удобству, а не ее отсутствие…
Ну с-но вы сами дальше про хаскель пишите, где так же консистентность приносится местами в угоду удобству :)
К слову вот в flow (типизированный js от фейсбука) тоже угарали по soundness, "более лучшему" выводу типов и другим вещам, которые любям теоретики. И нафиг никому не нужен теперь этот flow, в отличии от тс.
P.S. Кучу лет жизни я отдал работе с MMC оснастками, поддерживая и развивая воотчину лапшекода. Но потом в момент появления MMC 3.0 с поддержкой .Net, мой скилл очень быстро стал не нужен — новый инструментарий позволил молодым разрабам писать красивый код, использовать сторонние библиотеки, а не мучаться на C++ с встроенным IE 6 движком и передачей данных COM-объектами а-ля `COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)`. Так что, мало ли, может и JS в вебе что-то рано или поздно заменит. Ну или все привыкнут и будут работать как есть :)
Обмазать тестами и проблем не будет.
Тратить дополнительное время, а ради чего? Если компилятор уже содержит эти «тесты», достаточно лишь указывать типы.
Нет ничего страшного в том, что 1 + '1' — 1 = 10.
Страшно искать такие ошибки по косвенным признакам.
Тратить дополнительное время, а ради чего? Если компилятор уже содержит эти «тесты», достаточно лишь указывать типы.
Да блин, нет у JS никакого компилятора, он интерпретируемый!
Ну, признаться, в большинстве популярных реализаций JIT всё же есть. А это почти что нормальный (кейворд — "почти").
А касательно дискуссии выше, то на JS гонят справедливо, как справедливо гонят на PHP, C++ (ооо, там вообще эпичные баталии) и чуть ли не каждый первый язык. Все они не без недостатков; и хорошо что есть недовольные, иногда настолько, чтобы что-то менять к лучшему. Я сейчас выскажу крайне непрофессиональное и сугубо субьективное: JS легче убить, чем починить (мечты-мечты). Но я-то знаю, что это моя личная заморочка, которую, похоже, разделяет немало других людей, но менее заморочкой от этого она не становится. Но и выгораживать откровенно контринтуитивное поведение спецификациями — это точно такая же заморочка, только вида «прощу всё потому что этот язык мне нравится».
Очевидно, что в
var a = 42;
var b = '42';
var c = a + b;
и
var a = 42;
var b = 42;
var c = a + b;
Будут выполнены разные операторы, в первом случае — конкатенация, во втором — сложение.
Т.е. тут уже интерпретатор в курсе, что различие есть и типы известны. Почему не упасть с ошибкой вместо этого?
— ну а зачем в питоне код индентируется табами? Ну неудобно же пипец просто
— зачем в Паскале оператор присваивания ":=", два символа вместо одного?
— почему в джаве нет беззнакового целого (uint)?
— зачем в php строке конкатенируются через точку? странно и непривычно же.
Ну сделано просто так, когда это все делалось, тому кто это делал казалось что так вот де будет неплохо понимаете? Ну не расчитывали они, что через 20 лет этот язык попадет в руки лодырей которым сложно сделать проверку типа прежде чем что либо делать со значением. По всей видимости создатели всех вышеперечисленных проблем — просто были бездарными, недальновидными личностями, неспособными заглянуть в будущее.
Но вы ведь не такой да? Вы ведь нам напишете язык программирования лишенный абсолютно всех недостатков? Идеальный, абсолютный, такой чтоб и через 300 лет никто не нашел бы в нем ни единого изъяна.
Disclaimer: Я не пытаюсь доказать, что ЖС — уебанский язык и он должен немениуемо сгинуть прям вот сейчас. Более того, я считаю, что если его что-то и должно заменить, то это должно быть некое его развитие, чтобы переход был безболезненным. Хотя лично мне ЖС — не нравится, но это вкусовщина и я не навязывают своей ТЗ.
>Это написано в стандарте, поэтому мне не понятно зачем ему падать с ошибкой, тогда как в стандарте написано иначе.
Не в защиту РНР, но там тоже хотели простую конкатенацию строк и таки выделили для этого отдельный оператор, хоть и неудачно выбранный, на мой взгляд. И это лучше, т.к. поведение более явное и предсказуемое.
А когда появились классы пришлось вместо
this.value
писать $this->value
, так как точка была уже занята. При этом использований -> наверное в десятки раз больше, чем использований точки. Но исторически так сложилось, от этого уже не уйти.+ '1' + 1 == 2
Запретить делать 1 + '1'? Это странно, ибо интерпретатор/компилятор тогда должен парсить каждую строку
Нет ничего страшного в том, что 1 + '1' — 1 = 10.
Думается мне, мнение 0xd34df00d по поводу этих предположений было бы интересно послушать.
Какой контроль нужен? Запретить делать 1 + '1'?
Запретить передавать строку в функцию, которая ожидает увидеть там число. Ещё до того как код начнёт вообще в принципе выполняться. Сейчас глядя на сигнатуру функции даже понять невозможно, что она там ожидает. Typescript в этом плане ощутимо помогает, да.
По такой логике, можно выкинуть питон, php и другие языки с динамической типизацией.
Зачем выкидывать-то? Вон, на третий питон натягивают аннотации типов. В PHP хинты доступны ещё с пятой версии.
Но это же не от того, что его хотели выкинуть, это просто развитие. Как в C# добавили когда-то dynamic.
Динамическая типизация имеет свои плюсы и минусы, как и строгая. И писать, что JS говно и не подходит к веб из-за динамической типизации, как минимум странно.
if(typeof param1 !== 'string') { throw new Error('string expected'); }
if(!Number.isFinite(param2)) { throw new Error('not a number'); }
if(!Number.isInteger(param3)) { throw new Error('int expected'); }
typescript хорош и я бы на него с удовольствием перешел, даже не столько из за типов, но всю контору не пересадишь, было много попыток не только с моей стороны, а мы стараемся использовать тот же стек технологий в разных проектах.
При чем тут фреймворк?
Есть разница в подходах, когда пишется конкретный конечный код, в конкретной команде, вам не стоит тратить время на защиту от дураков. Если у вас в команде дураки, нужно или избавиться от них или повысить их квалификацию до «недурак». Фреймворк же это полуфабрикат, который неизвестно, кто потом будет использовать и да, там защита от дурака желательна.
Речь идет о конечном продукте, с которым работают пользователи, в которых могут возникать логические ошибки
В теории могут возникнуть, в реальности не возникают, проблема преувеличена, смотрите что вы делаете и все будет хорошо.
Почему программист должен об этом думать вообще и вручную проверять типы в рантайме и бросать исключения вручную.
Потому что у js нет времени компиляции и так сложилось исторически, но если вам нужны проверки до рантайма используйте линтер, он как раз делают ту работу компилятора по проверке соответствия типов и не только это. При этом там есть настройки от «и так сойдет» до закрутить гайки так, что дышать станет трудно.
но если вам нужны проверки до рантайма используйте линтер, он как раз делают ту работу компилятора по проверке соответствия типов
Линтер вам покроет едва ли единицы процентов от всех кейзов. Я уж не говорю про кейзы, когда хочется гарантировать какие-то совсем интересные вещи. Например — делаете вы запрос каких-то сущностей к серверу и можете указать список полей, которые в этих сущностях должны быть подгружены. Хочется, чтобы в список попали только те поля, которые реально есть, без опечаток, без лишних полей и т.д.
На типах это можно реализовать. В этом случае если, например, на сервере изменится апи, то вы можете автоматически перегенерить модели и вам сразу в нужных местах компилятор укажет на ошибки, если где-то в проекте используются какие-то поля, которые сервер не возвращает. В противном случае — успехов вам в отладке.
Линтер вам покроет едва ли единицы процентов от всех кейзов
В проектах, где используется хорошо настроенный линтер за все время, уже сколько лет, ни разу не было проблем с типизацией в рантайм. Находил все. Моя статистика 100%.
делаете вы запрос каких-то сущностей к серверу и можете указать список полей, которые в этих сущностях должны быть подгружены. Хочется, чтобы в список попали только те поля, которые реально есть, без опечаток, без лишних полей и т.д.
Да запросы к серверу и вообще к 3й стороне, это проблемное место, тут есть решения, можете проверять схему, можете написать тест который проверяет, что апи не изменилось. Изменение апи между отдельными модулями это всегда и везде проблема, на всех известных мне языках и платформах, вы не можете просто взять и изменить апи и вам за это ничего не будет.
По поводу чистоты, то что бы там ни было, но надо смотреть вручную или в фидлере или на вкладке «сеть», что там на самом деле туда сюда отправляется, сервер может добавить от себя немного мусора.
В проектах, где используется хорошо настроенный линтер
Линтер не может проверять типы. Как бы вы его ни настраивали. Он просто не обладает таким функционалом. Т.к., в первую очередь, нельзя проверить то, чего нет.
уже сколько лет, ни разу не было проблем с типизацией в рантайм
Они были, просто вы не считаете эти проблемы проблемами типизации. Хотя нормально написанные типы эти проблемы бы отловили.
Изменение апи между отдельными модулями это всегда и везде проблема
В описанной мной схеме никаких проблем нет.
сервер может добавить от себя немного мусора.
Не может. Сервер возвращает ровно то, что указано в типе соответствующего контроллера, иначе не скомпилируется.
/**
* @param {Date} date
* @param {Number} days
* @returns Date
*/
function addDays(date, days){} // даже без JSDoc понятно какие типы присылать, нет?
function addUser(user){} // речь о типе User
function addUser({firstName, lastName}){} // еще вариант сразу видеть, что функция ожидает
function setName(name){} // типов в js немного, очевидно name это строка, а не число
fuction setCounter(counter){} // counter - очевидно число
Я много лет писал на строго типизированных языках и поначалу мне было очень неуютно без типов, но сейчас я считаю, что без них лучше, меньше мусора. Но привыкание берет время.
fuction setCounter(counter){} // counter - очевидно число
Ну да, вам очевидно, ведь вы только что написали это! А мне вот совсем не очевидно. Может, это функция, которая возвращает число:
function createCounter () {
let i = 0;
return () => ++i;
}
А может инстанс специального класса? Про User для вас ведь почему-то очевидно, что это тип, а не строка, к примеру.
Да, пока у вас три строчки кода — оно всё очевидно.
function setName(name){} // типов в js немного, очевидно name это строка, а не число
Опс, а когда появился тип User в JS? Может name — это boxed-значение из какого-то реактивного фреймворка вообще?
function addUser(user){} // речь о типе User
Ну вот мне дали задание дописать какую-то фичу в эту (ну или похожую функцию). И как я буду знать, какие поля есть в user? Мне передадут нормальный объект или какой-то любитель динамической типизации решит: «а, пофиг, firstName и lastName будет достаточно, больше там ничего не нужно!». А если это вообще не инстанс класса, а какой-то hash, как сейчас модно (классы ведь пишут только задроты, сейчас у хипстоты в моде «недо-фп»). И ты никогда точно не знаешь, что можешь использовать там. Потому что даже если ты поставил бряку и посмотрел, что тебе прилетел объект, а в нем есть поле id, то в другом месте какой-то сторонник прогрессивного подхода решил, что id тут не нужен.
Проблема вашего примера в том, что он абсолютно стерилен. Пока это что-то простое из разряда «setName» — может оно и работает немного. Но возьмите любой говнокод на редаксе и чтобы понять, что вошло в функцию — необходимо поставить брейкпоинт, запустить браузер и посмотреть, что же туда приходит и какие поля есть у этого объекта. И именно в такие моменты начинаешь ненавидеть динамическую типизацию.
Но если сложность вашего кода уровня ваших примеров, то понятно, почему её вам достаточно
function createCounterFactory () {
let i = 0;
return () => ++i;
}
И как я буду знать, какие поля есть в user?
Так же как и с типами, вы посмотрите код или документацию. Бонусом чтения кода будет, что вы поймете не только какие параметры ожидаются, но так же как она работает. И все в одном месте, вам не нужно прыгать по классам.
А если это вообще не инстанс класса, а какой-то hash, как сейчас модно
Тогда напишите в сигнатуре
function addUser(userHash){}
так же как в java
void addUser(Hash userHash){}
Проблема вашего примера в том, что он абсолютно стерилен
Код в продакшен такой же, я стараюсь делать его очевидным и простым. Это способ сделать, что бы все работало хорошо. Баги начинаются, когда вы перестаете понимать, что здесь происходит.
Но возьмите любой говнокод на редаксе и чтобы понять, что вошло в функцию — необходимо поставить брейкпоинт, запустить браузер и посмотреть, что же туда приходит и какие поля есть у этого объекта. И именно в такие моменты начинаешь ненавидеть динамическую типизацию.
О, редакс не использую именно потому, что как ни крути, на выходе говнокод. С одной стороны на бумаге идея интересная, но если компонент небольшой, его не надо делить. Если же большой, то делить на маленькие компоненты, а не на не связанные абстрактные слои, в которых потом непонятно кто, где, кого. Абстракция хороша на высоком уровне. Внизу должна быть конкретность.
Но код который плохо написан — написан плохо, без связи с языком. На любом языке можно член сломать. Если вы не используете свой острый ум при написании кода, ни компилятор, ни юнит тесты, ни статик код аналисис, вас не спасут. Это всего лишь инструменты.
Если вы даете названия которые не отражают суть, то и типы вам не помогут, там тоже можно написать в названии одно, а по факту там будет другое
Не, если вы в типах что-то написали, то то самое там и будет. В этом и есть смысл статической типизации.
Так же как и с типами, вы посмотрите код или документацию.
В случае с типами я могу одной кнопкой переместиться к объявлению типа. В случае динамики — как это сделать, тип переменной ведь неизвестен? Что это за User? Где определен список его полей и вообще определен ли? Насколько документация соответствует коду? Точно никто в ней ничего не напутал или не забыл изменить?
Типы же — это та самая документация, корректность которой вам гарантирована компилятором и которая лучше поддерживается на уровне IDE.
Тогда напишите в сигнатуре… userHash
А зачем, если можно написать с типами "user: Hash", но при этом еще компилятор проверит, что там действительно хеш а не что-то другое, да еще и автокомплит будет нормальный для user._ внутри метода?
Если вы даете названия которые не отражают суть, то и типы вам не помогут, там тоже можно написать в названии одно, а по факту там будет другое и такое встречается, надо так: createCounterFactory
Э нет! Это нифига не фактори. Это у вас нейминг неправильный. Counter — этот тот, кто считает. Вот такая штука:
Не цифры на нём, а именно сам счетчик. Так что counterFactory — это что-то, что создает такие счетчики, которые возвращают цифры. Так что под вашим очень правильным неймингом я представляю что-то такое:
function createCounterFactory (startingValue) {
return {
createCounter: function () {
let i = startingValue;
return { next: () => ++i; }
}
};
}
const counterFactory1000 = createCounterFactory(1000);
const counterA = counterFactory1000.createCounter();
count value1 = counterA.next();
count value2 = counterA.next();
count value3 = counterA.next();
Так же как и с типами, вы посмотрите код или документацию. Бонусом чтения кода будет, что вы поймете не только какие параметры ожидаются, но так же как она работает. И все в одном месте, вам не нужно прыгать по классам.
Ага. Документацию. Хорошо, если она есть и вообще прекрасно, если она актуальная. Вот только вы прочитали мое сообщение через строчку. Как я могу быть уверен, что во всех местах, которые вызывают эту функцию передаются все поля? Какие ещё поля могут передаваться? А если этот кусок приходит с API сервера, то в клиентском коде вообще не будет этих данных. И вот зачем трахать себе мозг такими сложностями, если можно просто иметь тип и посмотреть всё необходимое одним кликом мышки?
Тогда напишите в сигнатуре userHash
О! Класс! А давайте тогда во всех названиях переменной писать её тип! userHash, counterNumber, lastNameString! Я прям захотел сразу отказаться от мусора статической типизации и внять вашим гениальным советам! А какие там поля userHash должен принимать, кстати?
Код в продакшен такой же, я стараюсь делать его очевидным и простым
Предполагаю, что ничего сложнее CRUD вы не писали.
Если вы не используете свой острый ум при написании кода, ни компилятор, ни юнит тесты, ни статик код аналисис, вас не спасут. Это всего лишь инструменты.
Абсолютно согласен. Человек, который не думает не сможет построить дом с самыми крутыми инструментами. Но зачем забивать гвозди камнями, если можно взять молоток?
Так получается я зря начал учить Python?
Вот блин :(
Так и думал, что надо Java брать.
Я закончил ВУЗ. По специальности инженер-программист.
В процессе обучения было около 10 ЯП. Разных. C, C++, Java, JavaScript, PHP, Verilog, VHDL и т.д. Это из того, что сходу вспомнил.
На данный момент я пишу на PL/SQL. Он со статической типизацией.
Я решил выучить язык по-полуряней. Что-то из списка: C#, Java, Python.
Java как-то в университете не зашла. С# отпугнул своей заточкой под Windows. В итоге остался Python.
Походу придётся засунуть подальше свои «хотелки» и взять или C# или Java.
С# отпугнул своей заточкой под Windows
Сейчас это уже не так, есть кроссплатформенный .NET Core. Если есть принципиальная нелюбовь к .NET, то можно взять Kotlin — это новейший язык под JVM, созданный для потенциальной замены Java.
Зачем заклёвывать? Я просто напомню, что курс SICP использует в качестве основного языка динамически типизированный Scheme.
Какие странные дороги у нас делают с канавами по бокам. Постоянно там в говно вляпываюсь
запустил бизнес и особо не лез в него — молодые лучше знают свое дело. А я бы занимался цветочками.
Но это же так не работает) Ничего плохого про героя интервью не считаю, но это звучит, как-будто человек вообще не имеет представления о предпринимательстве, однако делает на это ставку в будущем. В общем, как-то наивно звучит.
Я бы не стал связываться с Java, Spring Boot. Но Kotlin, да — это круто.
Пошло-поехало, "крутой" разраб.
В свое время на Flash я успел наговнокодить. Так получилось, что игрок делал двойную ставку: он видел одну фишку, а по факту ставил две.
То есть был ActionScript со статическими типами и классами, но все равно там тоже были баги?
А тут внезапно в Javascript типы динамические и все баги именно от этого. Танцор у нас хороший, только яйца динамическая типизация мешает.
Вопросы, конечно, вы меня извините.
Ответы на четвертый и шестой могут быть полезны широкой аудитории. А остальные — зачем? Какая разница, какие мониторы, ЯПы и книги предпочитает отдельно взятый дядька, будь этим дядькой хоть Алан Тьюринг?
- JavaScript, чтобы вы изменили или улучшили в индустрии?
- Господи! Программиста! Убейте его! Он складывает строки с числами и ждет непойми чего! Он ведет себя непредсказуемо!
Учился на Немецком факультете экономики и права в Грузии.
несколько раз перечитал
Алгоритмы устарели? Паттерны у вас там все устарели? Что? Сахар какой-то новый завезли для вашего языка? Фреймворк ваш обновился? Евангелисты блин
«Думаю, JavaScript не подходит для веба». 10 вопросов программисту, 4 выпуск (из Берлина)