LINUX.ORG.RU

Зачем нужна статическая типизация?, или Вы всё врете!

 ,


1

4

В теме "Питонячьи радости " на последних страницах между мной и @rtxtxtrx внезапно разгорелся спор, из которого я понял, что есть еще люди, которые не считают динамическую типизацию (в том виде, в котором она представлена в Питоне, а именно строгая динамическая типизация) серьезным недостатком при работе с большим объемом кода, особенно при рефакторинге. Вообще изначально разговор завязался вокруг назначения type hints введенных в Питон 3: я утверждал, что они нужны для создания семантических связей в коде, которые будут препятствовать внесению деструктивных изменений в код в результате опечатки или иной ошибки кодера (изменил код, в результате которого какое-либо выражение получило некорректное значение, которое тем не менее обладает схожим с корректным значением типовым контрактом, поэтому при запуске код не «упадет» сразу, указав на проблему); оппонент заявил, что они нужны для (само)документации и не более того.
Но потом выяснилось, что и царь-то ненастоящий (читай, статическая типизация). Не нужна она, просто именуй сущности понятно и уповай на строгую типизацию. А если типизация не строгая, то сами виноваты, у нас в Питоне всё ОК.
Поскольку тема большая и вкусная, я предлагаю всем обсудить этот очень важный вопрос в меру скромных сил и познаний каждого желающего. Обсуждение вторичных вопросов, как-то «статическая типизация нужна для генерации эффективного кода», «при динамической типизации тип только один, object» etc. не предусмотрено — спорим только о том, дает ли статическая типизация выигрыш, если надо перекраивать несметные тыщи kloc. Если есть вообще о чем спорить 😅.

★★★★★
Ответ на: комментарий от Vic

Более оптимальный для процессора вариант FreeAndNULL() выглядит так.

void FreeAndNULL(void **ObjPtr)
{
    void *Obj;

    if (ObjPtr == NULL)
        return;
    Obj = (*ObjPtr);
    (*ObjPtr) = NULL;
    if (Obj != NULL)
        free(Obj);
}

Благодаря промежуточной переменной, меняется порядок логических действий: сначала обработка переменной по адресу *ObjPtr, затем вызов free() - это приводит к тому, что генерируется ассемблерный код, в котором free() не будет вызвана как подпрограмма (с сопутствующим выделением стека и его освобождением), а благодаря совпадению прототипов функций FreeAndNULL() и free(), где с точки зрения процессора это две подпрограммы с одним параметром типа указатель, будет просто переход, т.е. jump _free.

Vic
()
Последнее исправление: Vic (всего исправлений: 2)

Ну то есть, уже есть предусловие, что код неправильный и приходится переписывать несметные тыщи loc. Какая собственно разница между статической и динамической типизацией? Скорее всего и тесты, и типы, и архитектура неправильные и всё надо будет снести и написать заново.

Все приверженцы тотальной статической типизации, которых я наблюдал, это на деле приверженцы максимальной производительности выполнения за счёт продуктивности разработчика. Вот хоть ты расшибись, нужно писать как Кармак, на сишечке, сразу без багов и оптимизировать каждый бит. Далеко не каждый софт нужно писать на века, и нет никакой гарантии что не появится какая-то особенная ISA, или специализированный ускоритель, где этот сишный код уже будет неактуален, к примеру сейчас нет трёхмерных игр на софтрендере. По большому счёту эти люди отрицают своеобразный рынок, балансирующий выгоды и затраты.

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

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

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

Ну то есть, уже есть предусловие, что код неправильный и приходится переписывать несметные тыщи loc.

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

Каких-то яростных приверженцев динамической типизации я не видел

Даже в этом треде их несколько, rtxtxtrx, например.

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

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

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

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

Сами посудите, одно дело если оперируешь достаточно простым логическим объектом типа «число» - тогда тип этого числа можно попробовать подобрать на автомате в зависимости от применяемых операций и диапазонов значений.

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

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

И совсем другое, если логический объект более сложный, например «круг» и «квадрат», тогда вывести их типы из примененных операций - мне видится попросту нереальной задачей.

Как компромиссный вариант, который и ограничивает область применения и дает некоторую свободу в выборе типов, скорее-всего подходят «шаблоны языка C++» (векторы, коллекции…).

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

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

Нет. Что вы описываете, называется выводом типов в как-раз таки статической типизации (хотя и не везде он есть). Динамическая типизация - это когда, где какие типы данных в программе, знает только программист (вернее, самонадеянно, — или не очень, если он опытный, — думает, что знает), а вычислитель не знает, за исключением случаев использования примитивных типов данных с помощью литералов (числа, массивы и т.д.). И узнает вычислитель все типы во время выполнения программы. В случае возникновения несоответствия типов есть две стратегии: «это не ошибка, ща замажем 😉» (нестрогая типизация) и «не могу молчать!» (строгая типизация).
При статической типизации программист и рад бы не знать порой все типы, но вычислитель не позволит выполнить программу, пока каждый тип не будет точно определен.

границы применимости динамической типизации

Такие же, как при употреблении алкоголя: пока голова еще способна контролировать происходящее. Дальше — ни-ни.

Virtuos86 ★★★★★
() автор топика

Тему не читал. Нужна для надёжности, эффективности кода, избежания ошибок типа "2" == 2, для среды разработки (со знанием о типе можно гораздо точнее подсказать методы, точку определения и т.п.). Но имеет и цену - разбухание кода и снижение гибкости. Поэтому оптимален автоматический вывод типов, необязательность статической типизации в каких-то случаях, наличие в языке типа «что угодно». А Питон - это кака, и типизация там - тоже кака.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 3)
Ответ на: комментарий от den73

«2» == 2

Что за бред ты пишешь? В питоне при сравнении типы не приводятся в отличии от PHP/JS (где результат true). В нем это False. Но тут вся тема состоит из таких заблуждений и банального незнания языка.

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

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

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

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

Ты думать не умеешь или программировать? Естественно, что в реальной жизни у тебя будет "2" != 2, но ты будешь ждать, что "2" == "2". Причиной ошибки будет как раз отсутствие статической типизации. Ошибка будет в том, что ты (или другая несчастная жертва гада) будешь ожидать на какой-то стороне сравнения один тип, а в реальности будет другой. Потому что нет статической типизации. Если бы ты умел думать или программировать, то ты бы понял, а так - ну не хватило тебя на это. Я в реальном проекте наступал на такие грабли с операцией in, когда у меня было (в унаследованном коде). "abc" in fgh, но я не ожидал той подлянки, что fgh - почти всегда массив, но в одном случае - строка. Что в свою очередь произошло из-за какого-то другого нюанса, типа ("abc") vs ("abc",). Но точно уже не помню. И многими другими способами можно на подобные грабли наступить.

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

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 5)
Ответ на: комментарий от den73

Я не идиот и не буду ждать, что «2» это 2. Я же писал тут, что я начинал с… C++. Там «2» это символ в ASCII-таблице со значением 50, а не 2

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

Ну, это ещё предстоит доказать. Если априори ты вместо того, чтобы попробовать понять, что пишут другие, всем бред диагностируешь, то и твой диагноз вызывает вопросы. И кроме того, «я начинал с С++» - это уже искалеченный разум.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

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

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

Доказывать, что ты не идиот. Что я не знаю? 2 == «2» - это булево выражение. Если a и b - переменные, в одной 2, в другой «2», то результат сравнения a == b может оказаться неожиданным, если внимательно не проследить за их типами. Почему это надо разжёвывать? Где я написал, что 2 == «2» - истина?

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

Причиной ошибки будет как раз отсутствие статической типизации

Неявное приведение типов же. Ты два литерала сравниваешь, при чём тут вообще статическая/динамическая.

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

А что, я должен каждому писать вместо 2==«2» многословную простыню? Ожидалось, что с полуслова поймут.

den73 ★★★★★
()
Ответ на: комментарий от den73
def f(a:int, b:str):
  if a == b:
    делайЧтоТо

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

def f(a,b):
  if a == b:
     делайЧтоТо

Если a и b - это 2 и «2», то делайЧтоТо не вызовется. И если программист не задумался о типах a и b, то он может очень долго не разобраться, в чём проблема. Так что отсутствие неявного приведения, как в JS, не спасает.

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

Если a и b - переменные, в одной 2, в другой «2», то результат сравнения a == b может оказаться неожиданным, если внимательно не проследить за их типами

Так ведь статическая типизация для этого не обязательна — достаточно просто не приводить типы неявно, и никаких неожыданностей не будет. Сделай 2 === "2", получи ожидаемый и предсказуемый false, и дело с концом.

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

у него все претензии сводятся к тому, что питон - это не похапе и в нем типизация более строгая чем в джаве с c++, но тема про статическую тупизацию… в интерпретируемом языке, ага. хотя cython позволяет, а еще nim…

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

В python нет ===. Не приводить типы неявно недостаточно. Достаточно просто невнимательно проследить за типами данных, приходящих извне. Я вот теперь задумался, есть ли в Питоне неявное приведение типов.

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

Я смотрю, уже толкователи моих слов появились, хаха. Только не надо перевирать. Да, tcl/tk - это мой язык, там ещё хуже с типизацией, чем в PHP, хотя я не знаю, как с ней в PHP, потому что на PHP я написал за всю жизнь строчек 10, наверное.

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

Интерпретируемость языка к типизации никакого отношения не имеет, неуч. Как пример, java является интерпретируемым языком (пока не сджитится).

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

Вот, кстати, в python "2" * 2 = "22". В нём нет знаменитого 2 + "2" = "22", но недалеко ушёл. Это тоже проблема типизации, но это не проблема её статичности или динамичности, это проблема перегрузки операций, которая и в плюсах, кстати, в полный рост. И она из той же серии, что 2 == «2». Отсутствие статической типизации здесь лишь является отягощающим обстоятельством.

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

Тебя не смущает, что питон это язык с перегрузкой операторов, где многие вещии делаются через эту самую перегрузку, например, dct |= {key:value} равнозначно dct.update({key:value}), 's' * 20 - это замена 's'.repeat(20)? Для конкатенации строк вместо . или .. используется + - ну обосраться теперь и не жить. Проблема то в чем?

2 + «2» = «22»

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

rtxtxtrx ★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 2)
Ответ на: комментарий от den73

Отсутствие статической типизации здесь лишь является отягощающим обстоятельством

Это скриптовый язык. Он не компилируется, господе иисусе. Какую ты статическую типизацию то захотел?

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

Ну если ты с C++ начинал, то тебе не понять. Другой бы на моём месте что-нибудь бы написал про трудное детство или ещё похуже. Но я просто скажу: ты начал не с того, с чего надо было. Поэтому твоё мнение теперь, ну, так скажем, мне не интересно.

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

Увы, он компилируется. На этом с тобой у нас всё кончено. Можешь что-нибудь обидное крикнуть мне вслед.

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

Да кресты учат не тому… что строки и числа сравнивать низя. Убьюсь теперь

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

Ага компилируется в опкоды, которые все равно интерпретируются

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

Это скриптовый язык. Он не компилируется, господе иисусе. Какую ты статическую типизацию то захотел?

Одно вообще не связано с другим :)

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

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

if ($cond) {
  require_once "lib/foo.php";
} else {
  require_once "lib/bar.php";
}

А еще всякие eval=evil есть, возможности сбрасывать кеш модулей и тп. Вот возьмем какой-нибудь код:

a: int = 42
b: str = "foo"
print(a + b)

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

Вся тема просто пропитана нетерпимостью и нежеланием последовать довольно правильному совету:

Завтра ищешь в интернете книжку Dive into python…

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

это не проблема её статичности или динамичности, это проблема перегрузки операций

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

Представь себе, если бы в лиспе кто-то в определённые моменты переопределял let.

Нет, я ни на что не намекаю %)

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 2)
Ответ на: комментарий от rtxtxtrx

ну это в твоей голове

Это в голове любого грамотного человека.

Какой смысл тут в статической проверке типов?

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

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

Представь себе, если бы в лиспе кто-то в определённые моменты переопределял let.

Как тот бородатый анекдот:

// счастливой отладки, ...
#define TRUE FALSE
rtxtxtrx ★★
()
Ответ на: комментарий от Nervous

мы интерпретируем значения или имена по-разному в разных контекстах

Справедливости ради надо заметить, что тут под раздачу попадает вообще любой полиморфизм. Я думаю, что отказываться от полиморфизма всё-таки не надо, надо просто делать его явным и очевидным.

Вот defun — это обычная функция, вот defgeneric — это полиморфная функция. Всё прозрачно и понятно, никаких сюрпризов. Не надо копаться в тоннах документации или в исходниках на сях, чтобы узнать, как оно там всё на самом деле (тм).

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

Мне видится, что я все-таки все правильно понял.

Но есть один вопрос: мы рассматриваем конкретные реализации в существующих языках или все-таки рассуждаем об этом в общем и целом?

Например, («2» == 2) и что бы было true, это как я понял есть псевдокод с желаемым поведением у одного из написавших.

Или вот тут как хотим, что бы было «42foo» или нет?

a: int = 42
b: str = "foo"
print(a + b)

Т.е. в моем понимании, любая работа с типами данных/операндов зависит от выбранной цели. Поэтому, считаю, что надо сначала определить цель, а потом уже рассуждать об пользе/вреде.

PS. Если что, я сторонник точной типизации (не жесткой, а точной) и считаю, что желаемый результат должен достигаться явным указанием в выражениях желаемого результата, в формуле/операндах – что бы взглянул на формулу и все было понятно четко и точно, без необходимости лазить в другие модули или части исходников. Но такого нигде не встречал, поэтому, я пока сторонник жесткой типизации, что бы все проверял и лазил сам компилятор, и если что-то не так, то подсвечивал и не давал компилироваться программе.

Псевдокод, иллюстрирующий мое видение динамической но точной типизации:

a: int = 42
b: str = "foo"
print(a as str + b as str)
Vic
()
Последнее исправление: Vic (всего исправлений: 12)
Ответ на: комментарий от Vic

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

Нет, это - неявное приведение типов.

Статическая типизация - это когда тип переменных является истинным и задает ограничения при их использовании

Нихрена оно не задаёт. Сделай тип int со значением от 10 до 90

Сами посудите, одно дело если оперируешь достаточно простым логическим объектом типа «число»

Нихрена оно не простое. Знаковое, беззнаковое, целое, вещественное, длинна, диапазон, какая точность операций нужна.

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

ДТ не про это, все следующие посылы мимо. ДТ - это (как не странно), про типизацию во время работы, а не до её начала.

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

Например, («2» == 2)

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

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 2)
Ответ на: комментарий от den73

Представляешь, а кто-то всю жизнь пишет на жс на "2" == 2 или 1 + "2" ни разу не прокололся. Как у них это выходит?

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

может оказаться неожиданным, если внимательно не проследить за их типами

Ну так а на что вы надеетесь, если нихера не следите за типами данных в **динамическом** языке? Кто за вас должен за ними следить?

Доказывать, что ты не идиот.

Доказывай.

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

ДТ - это (как не странно), про типизацию во время работы, а не до её начала.

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

Психика человека склонна делать ошибки, Это надеюсь всем очевидно. И статическая типизация - метод компенсации ошибок, которые обязательно совершит человек.

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

В этом проблема и есть.

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

Психика человека склонна делать ошибки, Это надеюсь всем очевидно

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

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

Например, в языках со статической типизацией можно делать собственные типы, объединяющие нужные (union в Си) или использовать контейнеры (std::variant в С++), или есть встроенные в язык (тип variant в паскале). Таким образом получаешь нужный тип в рантайме с полным контролем над вариантами обработки.

Т.е. обработать значения произвольного И известного типа, не проблема при любом типе типизации переменных.

(ответ в том числе и для @Virtuos86 и для агрессивного @crutch_master)

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

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

Vic
()
Последнее исправление: Vic (всего исправлений: 5)
Ответ на: комментарий от rumgot

Часть ошибок исчезла бы до запуска,

Зато другая бы часть появилась. Статическая типизация замедляет разработку, замедляет тестирование, замедляет проверку гипотез. При этом исчезают примитивные ошибки вроде сравнения числа со строкой, а появляются ошибки в бизнес-логике. Грусть-тоска, а как иначе?

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

Например, в языках со статической типизацией можно делать собственные типы, объединяющие нужные (union в Си) или использовать контейнеры (std::variant в С++), или есть встроенные в язык (тип variant в паскале). Таким образом получаешь нужный тип в рантайме с полным контролем над вариантами обработки.

А потом ты устраиваешься на работы и выясняется, что тип данных «Пользователь» по грехам нашим размазан между микросервисами авторизации (typescript) и биллинга (Go), монолитом, на который все плюются, но он делает всю работу, (ява) и базой данных (постгрес). Удачи выловить все ошибки на этапе компиляции чего-нибудь.

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

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

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

В этом нет проблемы, если не писать на дт языке, как на ст

Там за тебя всё уже решили, как приложение надо строить

Так надо делать проверки до того, как код начнёт работать

Тесты - один из способов

А так, можешь хоть каждый вызов функции описывать декларативно, кто тебе мешает.

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

Нет проблемы, если

Если язык позволяет это делать, то это будет сделано.

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

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

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

Ой, правда? А при разработке на динамически типизированных ЯП ошибок в бизнес логике нету. Ну правильно динамичность все ошибки бизнес логики сама решает.

Статическая типизация замедляет разработку, замедляет тестирование, замедляет проверку гипотез

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

rumgot ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)