Чи варто статичне введення тексту вигідних?


108

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

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

Це не порівняння мови, тому, будь ласка, не розглядайте такі питання, як компільований vs інтерпретований. Чи варто безпека типу вражати швидкість розвитку та гнучкість? ЧОМУ?

людям, які хотіли прикладу думки, що динамічне введення тексту швидше:

"Використовуйте динамічно набрану мову під час розробки. Це дає швидший зворотний зв'язок, час повороту та швидкість розвитку." - http://blog.jayway.com/2010/04/14/static-typing-is-the-root-of-all-evil/



8
@Prof Plum: чи можу я вимагати доказ того, що є швидкість розвитку та гнучкість? Оскільки ми говоримо про конкретний аспект типу Безпека , використовуючи Javaабо C#був би непереконливим, спосіб їх забезпечення НЕ єдиний ...
Matthieu M.

32
Старанно кажучи суворою мовою, ви можете мінімізувати «головні болі», і тоді ви навіть можете побачити збільшення швидкості завдяки автоматичному заповненню IDE, генерації коду та натяку на код.
Ніколь

9
@Prof Plum: Я розумію, я не сподіваюся, що ви (або хтось насправді) повністю перевірив кожну створену мову ^^ Проблема полягає в тому, що більшість людей, яких я бачив, скаржаться на певний аспект мов програмування (Статичний Введення тексту часто буває), як правило, скаржаться на певну реалізацію та не реалізують її.
Маттьє М.

5
@Prof Plum, все, що в публікації блогу дійсно має говорити про швидкість, - це лисий твердження: "Кожен, хто серйозно попрацював із сучасною динамічно типізованою мовою, на зразок Ruby або Smalltalk, знає, що вони продуктивніші". Немає фактичних прикладів того, як в практичному плані це робить швидший розвиток.
Carson63000

Відповіді:


162

Це свого роду міф, що програмістам не потрібно хвилюватися про типи в динамічно набраних мовах.

На динамічно набраних мовах:

  • Ви все ще повинні знати, чи працюєте ви з масивом, цілим числом, рядком, хеш-таблицею, посиланням на функції, словником, об'єктом чи будь-яким іншим.

  • Якщо це об’єкт, ви повинні знати, до якого класу він належить.

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

  • На нижчому рівні такі речі, як кількість біт або підписаних проти неподписаних часто, все ще потрібно враховувати, якщо, наприклад, ви заповнюєте пакет TCP.

  • Ви можете зіткнутися з проблемами, коли отримаєте нуль там, де дуже хотіли порожнього рядка. Іншими словами, ви все ще налагоджуєте помилки невідповідності типу. Єдина реальна відмінність - компілятор не вловлює помилки.

  • Я заперечую, що ви навіть не дуже економите набравши текст , тому що ви, як правило, хочете документувати в коментарях, який тип ваших параметрів функції замість того, щоб документувати це у своєму коді. Ось чому блоки коментарів у стилі doxygen набагато популярніші на практиці в динамічно набраному коді, де на мовах, які набираються статично, ви здебільшого бачите їх лише для бібліотек.

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


10
Мені доведеться оскаржити те, що досвідчені програмісти не роблять / не вводять таких помилок. Хороші розробники, які є скромними та визнають можливість їх помилок (а досвідчені розробники не завжди подібні), мають меншу ймовірність створити ці помилки.
Джей Джей Джей

12
Не можу більше погодитися з "Я б стверджував, що ви навіть не дуже економите". Ви в кінцевому підсумку документуєте типи в коментарях і перевіряєте їх у своїх тестах, що, якщо що, потребує більшого набору тексту та обслуговування (зрештою, вам потрібно пам’ятати, щоб оновлювати зазначені коментарі щоразу, коли ваші типи змінюються, і частіше за все ви не будете ).
Северин Козак

Ми витрачаємо набагато більше часу на документи документування нашого магазину Python, ніж заощаджуємо на багатослівній статично набраній мові, як C # або Java. Варто також зазначити, що новіші покоління мов, такі як Go і Rust, використовують умовивід, тому ви вводите "x: = new (Object)" замість "Object x = new Object ()".
weberc2

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

Так, замість того, щоб надати тип змінних, ви можете використовувати значення за замовчуванням або одиничні тести (вбудовані доктести) в Python. Крім того, в Python іноді ви можете мати дивні помилки з пропусками написань [рідше це трапиться, якщо ви використовуєте автозаповнення, яке часто можна використовувати, хоча не весь час на динамічних мовах], і вам доведеться з’ясувати, чи вводить self.bread = 5 хліб або переробляти його.
aoeu256

123

У міру того, як типи стають сильнішими, вони можуть вам більше допомогти - якщо ви правильно їх використовуєте, а не боролися з ними. Створіть свої типи так, щоб вони відображали ваш проблемний простір і логічні помилки, швидше за все, стануть невідповідностями типу компіляції, а не замінами часу виконання або результатами дурниць.


37
+1! "логічні помилки частіше стають невідповідностями типу компіляції, замість збоїв виконання або результатів дурниць": Дійсно хороша відповідь! Коли я задіюю більше часу, щоб створити свої типи, тоді код випливає більш природно, і він часто правильний, як тільки він збирається. Проектування типу означає розуміння домену та його операцій.
Джорджіо

78

Відмова: Я любитель типу;)

На ваше питання важко відповісти: Що таке компроміси ?

Я візьму крайній приклад: Haskell , він статично набраний. Мабуть, одна з найбільш сильно набраних мов, що існує.

Однак Haskell підтримує загальне програмування в тому сенсі, що ви пишете методи, які працюють з будь-яким типом, що відповідає певній концепції (або інтерфейсу).

Крім того, Haskell використовує Type Inference , так що вам ніколи не потрібно оголошувати тип змінних. Вони статично обчислюються під час компіляції, так само як інтерпретатор Python обчислює їх запуск програми.

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


Приклад стислості:

-- type
factorial :: Integer -> Integer

-- using recursion
factorial 0 = 1
factorial n = n * factorial (n - 1)

Окрім вбудованої підтримки, складно зробити ще більш коротким.

Приклад загального програмування:

> reverse "hell­o" -- Strings are list of Char in Haskell
=> "olleh"
> reverse [1, 2, 3, 4, 5]
=> [5,4,3,2,1]

Приклад виводу типу:

> :t rever­se "hell­o"
:: [Char]

який можна обчислити просто:

  • "hello"- це список Char(виражений як [Char])
  • reverseзастосовано до типу, [A]повертає тип[A]

Спробуйте це у своєму браузері


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

7
Я не знаю Haskell, але +1 для "насправді скаржилися на щось інше (багатослів’я, біль від переключення одного типу на користь іншого)"
Ніколь

1
@Aidan: Haskell - це мова, що розвивається. Haskell 98 був покращенням порівняно з Haskell 1.4; Haskell 2010 був покращенням в порівнянні з цим. Тим часом, варто відзначити, що протягом більшої частини свого життя Хаскелловий розум був допомагати досліджувати типові системи; багатопараметричні класи типів - один із прикладів того, де вдалося з’ясувати корисне розширення системи типу. (З іншого боку, функціональні залежності виглядають як щось із глухого кута.)
geekosaur

4
@Matthieu: WRT "Мабуть, одна з найбільш сильно набраних мов, яка існує, насправді", я побачу ваш Haskell і піднять вас Agda та Coq . (Я
дозволю,

1
@Matthieu: Асистенти-кореспонденти - це пряме застосування кореспонденції Кері-Говарда, тому вони лежать в мовах програмування серця (хоча і з досить обмеженими стандартними бібліотеками). Вони стоять на передньому краї дослідження залежних типів, оскільки вам потрібні залежні типи, щоб добре використати листування "типи - пропозиції".
geekosaur

37

Мені подобаються як моменти статичного типу, так і динамічно набрані. Дві найбільші переваги безпеки для мене типу:

1) Ви можете дуже часто зробити висновок про те, що функція виконується виключно з її підпису типу (це особливо стосується функціональних мов, таких як Haskell).

2) Коли ви робите значний рефактор, компілятор автоматично повідомляє вам все, що вам потрібно зробити, щоб все працювало. Коли я рефактор щось в C ++, моя процедура часто просто а) змінити ту частину, яку я знаю, я хочу змінити, а потім b) виправити кожну помилку компіляції.


Точно так само і зі мною, і коли б я хотів щось переробити (я в основному використовую голанг / машинопис / java), так, ці 2 кроки - це те, кому кому знадобиться. змінити одну частину, а потім виправити всю помилку компіляції :) ідеальна відповідь.
Ніщал Гаутам

29

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

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


13

Є багато сильних думок навколо дискусій, але очевидно, це насправді не питання думки, це питання фактів . Отже, ми повинні подивитися на емпіричне дослідження . І докази цього зрозумілі:

Так , статичний набір вартий компромісів - і не лише трохи, а фактично істотно . Насправді, ґрунтовні дані свідчать, що статичне введення тексту може зменшити кількість помилок у коді принаймні на 15% (а це низька оцінка, фактичний відсоток майже напевно більший). Це вражаюче велика кількість: я думаю, що навіть більшість прихильників статичного набору тексту не могли б подумати, що це настільки різко зміниться.

Подумайте про це: якщо хтось сказав вам, що існує простий спосіб зменшити помилки у вашому проекті на 15% протягом ночі, це повинно бути незрозумілим. 1 Це майже прислівна срібна куля.

Докази представлені в документі " Ввести або не набрати": кількісна оцінка виявлених помилок у JavaScript від Чжен Гао, Крістіан Берд та графа Т. Барра. Я закликаю всіх її прочитати, це добре написаний документ, який представляє зразкові дослідження.

Важко коротко підвести підсумки того, наскільки суворо автори виконували свій аналіз, але ось (дуже приблизний) контур:

TypeScript і Flow - це дві мови програмування на основі JavaScript, які, залишаючись в іншому випадку сумісними, додають підказку типу та перевірку статичного типу. Це дозволяє збільшити існуючий код за типами, а потім перевірити його.

Дослідники збирали проекти з відкритим кодом, написані в JavaScript від GitHub, розглядали вирішені звіти про помилки та намагалися зменшити кожну з повідомлених помилок до фрагмента коду, який би потрапив у перевірку статичного типу TypeScript або Flow. Це дозволило їм оцінити нижню межу відсотка помилок, які можна було б виправити за допомогою статичного набору тексту.

Дослідники вживали суворих запобіжних заходів, щоб гарантувати, що їх аналіз не вважатиме помилку, що не стосується типу, як пов’язану з типами. 2

Порівняно з минулими дослідженнями, це нове дослідження має особливі переваги:

  • Існує пряме порівняння статичного та динамічного набору тексту з кількома (якщо такі є) заплутаними факторами, оскільки єдиною різницею між JavaScript та TypeScript / Flow є введення тексту.
  • Вони виконують реплікацію в декількох вимірах, перевіряючи і TypeScript, і Flow (тобто системи різних типів), і шляхом того, щоб різні люди відтворювали анотацію (вручну) типу, щоб виправити помилки. І вони виконують це у великій кількості баз коду з різних проектів.
  • У роботі вимірюється прямий вплив статичного набору тексту на помилки, що виправляються (а не на якусь більш невиразну якість).
  • Автори визначають сувору модель того, що вимірювати, і як наперед. Крім того, їх опис неймовірно зрозумілий і дозволяє легко проаналізувати недоліки (це завжди добре, коли дослідницький документ відкриває себе для атак: якщо жодним з атак не вдасться вбити свої аргументи, він вийде ще сильнішим). 3
  • Вони виконують належний аналіз потужності, щоб їх розмір вибірки був достатнім, а подальший статистичний аналіз був герметичним.
  • Вони надмірно консервативні, щоб виключати заплутані пояснення, і вимірюють лише одну рухому частину. Крім того, вони обмежують свій аналіз помилками, які можна негайно виправити, включивши типи, і виключають все, що може потребувати більш вдосконаленого рефакторингу для приведення тексту. Тож насправді ефект, ймовірно, набагато більший, але, безумовно, не менший, ніж те, про що вони повідомили.
  • І, нарешті, вони не знаходять незначного ефекту, але приголомшливої різниці. Незважаючи на їх надмірно консервативну процедуру, навіть у нижньому кінці 95% -го довірчого інтервалу вони виявляють, що є щонайменше 10% помилок, які просто зникнуть з мінімальними перевірками на доданий тип.

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


Як свідчить історична примітка, дослідження типізації дисциплін у програмуванні розпочали неабиякий початок, оскільки тривалий час докази взагалі не були чіткими. Причиною цього є те, що робити систематичні експерименти для дослідження ефекту статичного проти динамічного набору тексту непросто: систематичний експеримент повинен ізолювати ефект, який ми досліджуємо. І, на жаль, ми не можемо виділити ефект дисципліни набору тексту, оскільки він прив’язаний до мов програмування.

Насправді існували мови програмування, які дозволяли вводити як статичне, так і динамічне введення в різні діалекти (наприклад, VB з Option Strict Onабо Off, або статично набраний Lisp). Однак вони були не дуже придатними для прямого порівняння, головне, тому що не було існуючих, досить великих баз коду, які дозволяли би безпосередньо порівняти. У кращому випадку ми могли б порівняти їх у "лабораторних налаштуваннях", де випробувані випадковим чином вирішують завдання в статично або динамічно набраному варіанті мови.

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

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


1 Натхненний цитатою з оригіналу статті.

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

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

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


3
Я знаю, що це пізня відповідь на це питання, але я вважаю, що нові докази (які я пояснюю тут) змінюють повну дискусію щодо статичного проти динамічного.
Конрад Рудольф

2
Це, звичайно, цікаво, але мені цікаво, наскільки це стосується конкретної типової системи javascript. Система типу Python (особливо python3) набагато суворіша з набагато меншими неявними перетвореннями.
Пітер Грін

@PeterGreen Так, це, без сумніву, правда. Можливо, нам пощастило, і підказки типу Python призведуть до подібного аналізу в дорозі (хоча я сумніваюся в цьому, оскільки виражена мета в PEP484 & PEP526 - не застосовувати статичну типізацію).
Конрад Рудольф

1
Лише читаючи конспект, я вже можу сказати, що методологія принципово хибна. Ви не можете використовувати кодову базу, написану за допомогою однієї дисципліни, а потім просто додавати типи для виправдання аргументів у зовсім іншій дисципліні. Код, написаний як статична дисципліна, виглядає принципово зовсім інакше, ніж динамічна дисципліна, ви не повинні писати Java на Python, як і ви не повинні писати Python на Java. Навіть машинопис і javascript - принципово різні мови, незважаючи на поверхневу схожість.
Лежать Раян

2
@LieRyan Якщо що-небудь, що робить аналіз занадто консервативним, як зазначено в моєму описі та в інших місцях. Це аж ніяк не приводить до недійсності аналізу. Ваша оцінка на 1%, чесно, смішна. Це повністю вимкнено, ваша інтуїція підводить вас. Аналогічно, ваша характеристика проблем зі статичним набором тексту характерна для практикуючого динамічного набору тексту, який не мав фактичного досвіду роботи із сучасним статичним введенням (тобто не лише Java).
Конрад Рудольф

12

Чи варто безпекувати тип швидкості розвитку та гнучкості?

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

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

Це насправді мислення. Чи один кращий за інший? Це дійсно залежить від того, хто ти є і як ти думаєш. Більшість людей, з якими я працюю, ніколи б не торкалися динамічної мови, якби їм не довелося, тому що вони вважають, що є занадто багато місця для помилок. Чи помиляються вони так? Ні, звичайно, ні, але це означає, що вони зрозуміли, що їх підхід до застосування стилю кодування не буде працювати в динамічному середовищі. Інші люди, з якими я переходжу до груп користувачів, - навпаки. Вони вважають статичне введення тексту занадто громіздким, оскільки це обмежує їх підхід до вирішення певних типів проблем.

Чесно можу сказати, я дуже стрибаю між JavaScript та C #. Тепер, знання і робота на обох мовах певною мірою впливає на інших, але насправді, код, який я пишу в кожному погляді, повністю відрізняється від іншого. Вони вимагають іншого підходу, оскільки вони принципово різні. Я знайшов, що якщо вам здається, що ви думаєте: "Людина, це набагато складніше зробити це мовою X", ваш підхід, мабуть, трохи відхилений. Ось приклад, люди говорять про "піфонічний" спосіб здійснення справ. Це означає, що існує спосіб роботи мови Python, щоб полегшити проблему. Зробити це якимось іншим способом, як правило, важче і громіздніше. Ви повинні перейняти горбистість того, як мова працює, щоб вона справді працювала для вас. Це '


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

7

Нещодавно було задано подібне питання: Динамічні та Статистично типізовані мови для веб-сайтів

Щоб відновити основу моєї відповіді:

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

Так, Java суворо набрана, і так, Java смокче (не ображається. Це жахливо. Відмінна платформа та екосистема, але одна з найгірших мов, що коли-небудь (фактично використовується)).
Але виходячи з того, що суворе набирання текстів смокче - лише помилка. Це як вказівка ​​на PHP і підведення динамічного введення смоктання (знову ж таки, без образи. Повільно поліпшується, я даю вам це).

Особисто я більшу частину свого розвитку займаюсь у haXe , який має систему статичного типу. Він не тільки значно виразніший, ніж у Java, і вимагає набагато менших зусиль за рахунок виводу типу, але це також необов'язково. Якщо він коли-небудь стане вам на шляху, ви просто обійти його.

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

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

Приклад коду haXe:

class Car {
    public function new();
    public function wroom() trace('wroooooooom!')
}
class Duck {
    public function new();
    public function quack(at) trace('quackquack, ' + at + '!')
}

function letQuack(o) o.quack();
letQuack(new Car());
letQuack(new Duck());

Це призведе до помилки часу компіляції:

Car should be { quack : Void -> Unknown<0> }
Car has no field quack
For function argument 'o'
Duck should be { quack : Void -> Unknown<0> }
Invalid type for field quack :
to : String -> Void should be Void -> Unknown<0>
For function argument 'o'

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

Скажіть, що вам не потрібна безпека типу, оскільки у вас є тести, це ще більше ідіотично. Написання тестів нудне і повторюване. І я дійсно не хочу писати тест, аби тільки з'ясувати, що примірник Автомобіля не здригнеться, а Качка потребує когось, щоб стукати.

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


У python доктести просто копіюються та вставляються з repl / shell, як джерело документації та пізнішої перевірки. docs.python.org/3/library/doctest.html
aoeu256

5

З будь-якої причини я часто не роблю помилок, пов’язаних з типом об'єкта. У таких мовах, як C #, я, швидше за все, роблю помилки, пов’язані із закидами часу виконання, ніж я можу зробити помилку безпеки типу компілятора, яка, я даю, зазвичай викликана випадковою потребою обходити статичність статично набрана мова. Коли я пишу рубін, код, як правило, досить сильно натякає на тип об’єкта, а наявність REPL означає, що я вже експериментально перевірив, що потрібний метод / атрибути існують, або у мене буде тест одиниці, який робить в основному те саме, тому я також рідко стикаюся з проблемами безпеки в рубіні.

Але це не означає, що статично типізовані системи не можуть бути кращими, ніж вони є.

У мовах статичного типу типова система насправді має велике значення. Наприклад, з чимось на зразок Some monad у функціональних мовах (тип <Some>: = так x | ні), ви отримуєте перевірки часу компіляції, які по суті запобігають жахливий NullReferenceException, поширений у більшості типів систем; коли запускається код відповідності шаблону, ви отримуєте помилки часу компіляції, повідомляючи про те, що ви не впоралися з умовою нуля (якщо ви використовуєте цей механізм для оголошення типу). Ви також зменшуєте подібні помилки, коли використовуєте такі речі, як |> оператор конвеєра у F #.

У традиції Hindley – Milner статичного набору тексту можна створювати речі, які дають вам набагато більше, ніж гарантію того, що тип претензій підтримує інтерфейс X, і коли ви матимете ці речі, я б сказав, що статично набрана система стає багато більш цінним.

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


5

Це залежить.

Режими людської недостатності часто є статистичними. Ретельна перевірка типу знижує ймовірність виникнення кількох певних типів людських збоїв (що спричиняє помилку). Але те, що ти можеш зазнати невдачі, не завжди означає, що ти будеш (Мерфі не витримує).

Чи варто це зниження потенційних шансів на відмову, залежить від вартості.

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


3
У вашому сценарії швидкого складання прототипів натякається на помилку в статті Пола Худака про дослідження військово-морського флоту США, яке вимагало розробити подібне до AEGIS моделювання на різних мовах, однією з яких був Haskell. Він відповідає майже всім вашим критеріям: це було швидке складання прототипів, вимоги, де чітко визначено, а вартість відмови була майже нульовою (це надзвичайно неформальний експеримент). Haskell вийшов переможцем у категорії evey: час розробки, що перевищує вимоги, вимагає меншої кількості LOC, і єдиний робочий приклад серед усіх учасників!
Андрес Ф.

2
Доповідь: Haskell vs ..., Експеримент у продуктивності прототипування програм - Пол Худак та Марк П. Джонс . У ньому описані результати експерименту, замовлені ARPA та ВМС США.
Андрес Ф.

Чи не був переможець Relational Lisp? Людина, я хотів би, щоб там були види, які показують людям, що кодують речі в Lisp, з усіма такими дивними потужними розширеннями, як Shen (логічно-реляційна рамка, яка дозволяє надати залежним типам код і тип змішування та відповідності з нетиповим кодом ), супер-рамки CLOS з відправленням предикатів тощо ...
aoeu256,

4

Було багато дуже складних систем, написаних на Ліспі, і я не чув жодного Ліспера, який скаржився, що їм хочеться статичного набору тексту. Коли я працював з ним, я не пам’ятаю жодних проблем, які мене сильно уповільнили, що система статичного типу (і типично можна вказати типи у Common Lisp).

Більше того, основні статично набрані мови, здається, не дуже підходять для введення помилок. При розробці макета, що важливо, що певне число є вертикальним виміром на сторінці, що не є це int, unsigned, floatабо double. З іншого боку, компілятор часто конвертує тип прапорця, який він вважає небезпечним, і мені щасливо дозволити додати вертикальне вимірювання та кількість символів у рядку. Ця слабкість системи статичного типу була первісною ідеєю угорської нотації Сімоні, перед тим, як вона була вбита в потворну марність.


4

Типи є обмеженнями для інтерфейсів, тому вони є підмножиною того, що ви можете перевірити за допомогою тестів одиниць, і тому багато компромісів схожі:

  • Статичні типи надають попередні відгуки про те, чи відповідає код вимогам, які може бути висловлена ​​системою типів, в обмін на затримку зворотного зв’язку зі створенням мінімально функціонального (наприклад, відгуки клієнтів або випробування вищого рівня).
  • Знаючи, що код відповідає певним вимогам, може полегшити рефакторинг та налагодження, але він також додає накладні витрати на зміну інтерфейсів та зміну вимог.
  • Зокрема, якщо статично набраній мові не вистачає примусу, вона забезпечує додаткову безпеку від використання коду для даних, які можуть викликати помилки (зменшення потреби в умовних умовах і твердженнях), але надто обмежувальні обмеження вимагають від користувача ввести більше коду для масажування своїх даних у прийнятна форма (наприклад, явне кастинг типу).
  • Анотації явного типу можуть допомогти зрозуміти під час читання коду, або вони можуть захаращувати код із зайвою чи непотрібною інформацією.
  • Залежно від реалізації, це може погіршити лаконічність. Це залежить від речей, таких як необхідні або зроблені анотації типу, наскільки добре система типів може виражати загальні типи / інтерфейси, синтаксис і від того, чи ви планували випробовувати обмеження, які можуть бути виражені системою типів (тобто той самий тест, швидше за все, більш короткий як мовна особливість, ніж як одиничний тест, але ви, можливо, не мали наміру його перевіряти).
  • Крім того, статичні типи (але не пов’язані з TDD) можуть сприяти компіляції оптимізації часу за рахунок необхідності перевірки типів (і для того, щоб перевірити їх та виконати оптимізацію), а також можна зробити кращу оптимізацію, якщо дані обмежені типами що добре збігається з обладнанням. Це полегшує розробку коду з вимогами щодо продуктивності, але може спричинити проблеми з кодом, який не відповідає цим обмеженням (відповідно до пункту 3).

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


3

Так, звичайно. Одне, що ви знайдете, коли ви використовуєте як сильно набрані мови, так і Python (Python сильно набраний) - це те, що більшість добре написаних кодів у динамічних мовах, як правило, дотримуються багатьох тих самих умов, що і сильно набраний код. Динамічна типізація дуже корисна для серіалізації та десеріалізації, але для більшості інших речей вона не дає великої переваги. І якщо більша частина вашого коду пов'язана з серіалізацією, навіщо викидати безкоштовну перевірку помилок?


4
Сильно набрані мови, такі як Java та C #, автоматично обробляють десяріалізацію за допомогою Reflection.
Маттьє М.

3

Морган, у мене з’явилася цікава ідея спробувати: статичний + динамічний набір тексту. Ви згадали Python, C # та Java. Чи знали ви, що є кілька непоганих портів Python для .NET і Java? В обох випадках порти дозволяють використовувати бібліотеки цих платформ та / або взаємодіяти з існуючим кодом. Це дає кілька можливостей:

  1. Зберігайте застарілий код статичною, негнучкою мовою. Використовуйте Python для нових матеріалів.
  2. Використовуйте Python для прототипування нових речей на зрілих платформах. Перекодируйте компоненти, які ви хочете зберегти, на більш зрілій мові.
  3. Використовуйте динамічну мову для часто змінюваних частин.
  4. Можливо, використовуйте динамічну мову, щоб грати з такими ідеями, як зміна запущеного коду.
  5. Робіть все на динамічній мові, крім критичних частин, де ви використовуєте сильно набрану мову.

Я використовував ці підходи ще в кінці 90-х, щоб подолати біль, що розвивається в C / C ++. Мені потрібні були рідні бібліотеки, а іноді і вистава. Тим не менш, я хотів, щоб кращий синтаксис, гнучкість, безпека і т. Д. Отже, хитрість ретельно поєднувала їх, щоб отримати правильні компроміси. На практиці це часто було краще, ніж викидання цілої мови та застарілого коду для іншої мови / платформи.

(Примітка. Відповідь вже сказала це, але я також хочу ще раз підкреслити, що динамічне введення тексту! = Ні / слабке введення тексту. Багато систем динамічного типу використовують сильне введення зсередини. Те, як я думаю про те, що робить динаміку типу, полягає в тому, що тип змінних визначається під час виконання, не потребує анотації про тип та / або може змінюватися під час виконання.


2

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


це суб'єктивний контроль якості, тому я з цим добре.
Морган Херлокер

1
Комусь хочеться пояснити проголошення?
pdr

Не можу допомогти вам у поясненні, але я дав вам +1, я думаю, що це корисний внесок. Один з ключових побоювань при динамічному введенні тексту полягає в тому, що ви внесете зміни десь і зламаєте щось десь внаслідок припущень, які були б застосовані компілятором статично набраною мовою. Тут буде захищено важке покриття з випробування на важких одиницях.
Carson63000

5
Я не спровокував, коли ви зробили справжню точку, хоча жодних злочинів не мав на меті, але ваш пост зустрічається як маленький фан-бойок, тому, мабуть, тому і голоси.
Карл Білефельдт

@Karl, Образи не було, це було справжнє питання. Я можу бути неапологічно про-TDD, я визнаю
pdr

2

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

Моя остання робота в основному була розробкою пітона. Я працював у великій міжнародній компанії, що займається веб-хостингом, у нас були команди розробників у США, Канаді та Південній Кореї. Спеціальна веб-основа python для клієнтського додатка, що дозволяє користувачам управляти своїми доменними іменами та обліковими записами веб-хостингу. Бекенд: також усі пітони. Веб-сервіс Python для спілкування з окремими серверами, щоб зробити такі речі, як надання нового веб-сайту для розміщення веб-хостингу, створення нового блогу, створення записів dns в нашій системі обслуговування імен; і т. д. і т. д. На моїй теперішній роботі клієнтські додатки все це в Java; наш основний продукт - це суміш Java та флеш. Спеціальна веб-рамка Java для старих додатків, хвіртка для нових сучасних інструментів.

Працюючи в обох, я мушу сказати, що це питання клопоче мене кожного разу, коли я його бачу. Якщо ви користуєтеся динамічно набраною мовою і фактично перевіряєте свій код, у вас все буде добре. Якщо система спроектована добре, і ви дотримуєтесь стандартів, вам буде все в порядку. Ніколи не було багато помилок, які з’явилися через відсутність типів перевірки компілятора. Більшість помилок були логічними помилками, подібно до моєї роботи в java сьогодні.


2

Чи варто безпека типу вражати швидкість розвитку та гнучкість? ЧОМУ?

Статичне введення тексту - це чисте збільшення швидкості та гнучкості розробки протягом усього життєвого циклу програмного забезпечення. Це зменшує загальні зусилля та незручності, але переносить багато зусиль і незручностей вперед, куди це помітніше. Шлагбаум для введення робочого коду вище, але як тільки ви перейдете цей бар'єр (задовольнивши перевірку типу), розширення та підтримка цього коду вимагає набагато менше роботи.

Завжди будуть якісь головні болі в розробці програмного забезпечення через:

  • Притаманна складність того, що ви намагаєтеся досягти

  • Притаманна помилковості людини, особливо враховуючи, що ми робимо більше помилок, коли намагаємось зробити щось складніше

Рано чи пізно вам потрібно зайняти деякий час, щоб вирішити ці проблеми. Не обійти цього. Статичне введення тексту просто вирішує ці проблеми швидше, ніж пізніше. Чим швидше краще, ніж пізніше, адже чим пізніше ви виявите помилку (не питання про те, якщо , але коли ), тим більше коштує виправити цю помилку.

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


1

Це лише моя власна думка, але ні, я не думаю, що безпека цього типу не варта. Навіть ні на секунду.

Я давно розробник. Починаючи з c ++, c #, потім переходимо до javascript (frontend та backkend через node.js). З тих пір, як я розвиваюся в javascript, моя продуктивність зросла до неба, до того, що я фактично посилююсь за допомогою мов на основі типів. Я також проти компіляції, я хочу, щоб зараз все було в роботі. Інтерпретовані мови - це справді там, де я знайшов свою любов до програмування.

Щодо типів, я просто не бачу жодних переваг. Зараз я бачу типи так само, як я бачу управління пам'яттю. Зовсім непотрібне. Мови завтрашнього дня повинні повністю захистити розробника від того, щоб знати щось про типи. Комп'ютер повинен розуміти типи та залишати розробника поза ним.

Ось приклад. Я просто використовував Swift (нову мову Apple), сподіваючись, що він дійсно дожив до своєї назви день тому і спробував це зробити: var n = 1/2 не вийшло. Я був таким, що тут відбувається. а потім сумно зрозумів, що я повинен зробити var n: Float = 1/2. Це нагадало мені, наскільки я ненавиджу системи типів і наскільки вони є непотрібними.

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

Розробники люблять говорити, що слабко набрані мови не підходять для великих проектів. Але я б сказав, що це навпаки. Сильно набрані мови є жахливими для великих проектів. І якщо ви скажете, що JavaScript не працює для великих проектів, попросіть Uber в 40 млрд. Доларів + компанію, яка працює за всіма її архівами на node.js / javascript або Facebook, що почалася з PHP.

Що стосується статично набраних мов, це не добре для сьогоднішніх швидких ітерацій. ось простий приклад, у вас є 10 розробників, які працюють над проектом .net із сервером безперервної інтеграції, один розробник подає помилку, і вся збірка порушена, хоча 10 розробників працюють над різними речами, вони зараз усі зупинені і чекають щоб скривджений розробник виправив свою помилку. Говорити про ефективне так? Тип системи / статичні мови таким чином взаємозалежні і роблять ваш код взаємозалежним. Однак файли сценаріїв ніколи не взаємозалежні. Якщо є проблема з одним із сценаріїв, який не зупиняє виробництво, всі проблеми, які ви побачите, залишаються на час виконання. І час виконання ніколи не припиняється. Він ніколи не ламається. Це може дати неправильний вихід, але це не '


1
Багато "я", не багато суперечки. І, до речі, чи "помилка" помилка "збірки" не має нічого спільного зі статичною та динамічною. Якщо у вас є одиничні тести, і один з них не вдається "ваша збірка порушена" і, сподіваємось, не буде розгорнута до виробництва, поки це не виправлено
nafg

Що змусило вас подумати, що я маю на увазі щось таке?
nafg

Ваша продуктивність у javascript не зросла, оскільки у JavaScript не вистачало типів. Ви підвищили продуктивність, оскільки C ++ і C # - важкі мови. Типи Javascript + фактично ще більше підвищить вашу продуктивність. Ніхто не сказав, що javascript неможливий для великих проектів. Javascript для великих проектів, безумовно, можливий. Однак це не ідеально. Експериментальні випробування проводяться замість перевірки типу, також одиничні випробування мають обмежений тип покриття, тоді як перевірка типу має 100% покриття.
Брайан Єх

1
@BrianYeh c ++ і c # - важкі мови, оскільки вони зосереджені на типах. Я щойно почав використовувати reactjs на своїй роботі, і моя продуктивність знову знизилася через його постійне використання на типи та компоненти. якщо вам подобаються типи та одиничні тести, добре для вас. не всі з нас поділяють цей стиль програмування.

1
@foreyez reactjs не має типів. Ви, мабуть, маєте на увазі потік. Одиничні тести проводяться замість перевірки типу, тому якщо у вас немає перевірки типу, вам потрібно більше одиниць тестів. Одиничні випробування та типи є протилежними силами. Ваша продуктивність знижується - це ілюзія. Будь-яка помилка типу, яку ви виявите на безпечній мові типу, є інакше помилковою помилкою в динамічно набраній мові. Він з’являється тільки швидше. Мова безпечного типу змушує вас звертатися до цих помилок.
Брайан Єх

0

ТАК.

Я працював у PHP-додатках, де типи не такі «сильні», як у Java або C #. Зазвичай я закінчував "моделювання типів", тому що, щоб уникнути поганих автоматичних перетворень або перевірки даних.

Мови динамічного типу корисні для сценаріїв ОС та швидких невеликих додатків., А не складних програм.

Короткий зміст: Якщо мені доведеться вибирати мову програмування "Слабкий тип" або "Динамічний тип" або мову програмування "Сильний тип" для складної бізнес-програми, я вибираю мову програмування "Сильний тип" .


0

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

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

Ще одна більш тонка проблема - це недосконала замінюваність.

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

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

Два найпоширеніші типи програмування - це числа та рядки. У багатьох динамічних мовах вони є недосконалими замінниками один одного. Скажімо, javascript або php, якщо ви вказали номер, де очікується рядок, або навпаки, ваша програма працює без помилки, але може поводитися неправильно.

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

Однак це не уникло проблеми недосконалості сприйнятливості повністю. Різні типи числа можуть бути недосконалими замінниками один для одного, тому можуть бути різні типи послідовностей.


Що я тут отримую - я не думаю, що можна порівняти переваги та витрати статичного та динамічного введення в загальному вигляді, тому що я думаю, що і користь, і витрати залежать від конкретного варіації статичного чи динамічного введення мови. використовує.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.