Автор оригинала: FreeCodeCamp Community Member.
Preethi Kasireddy
Мы покрывали много земли в Часть 1 ! С помощью синтаксиса, давайте, наконец, доберемся до удовольствия: изучение преимуществ и недостатков использования статических типов.
Преимущества использования статических типов
Статические типы предлагают много преимуществ при написании программ. Давайте рассмотрим несколько из них.
Преимущество № 1: Вы можете обнаружить ошибки и ошибки рано
Проверка статического типа позволяет вам убедиться, что инварианты, которые мы указали, верны без выполнения программы. И если есть нарушение этих инвариантов, они будут обнаружены до времени выполнения, а не во время этого.
Быстрый пример: предположим, что у нас есть простая функция, которая принимает радиус и рассчитывает область:
Теперь, если бы мы проходили радиус, который не является числом (например, «злой») …
… Мы вернулись Нан
Отказ Если какой-то функционал полагался на это Calculatearea
Функция всегда возвращая номер, то этот результат может привести к ошибке или сбою. Это не очень приятно, это?
У нас использовали статические типы, мы могли бы указать точные входные (ы) и типы выходов для функции:
Попробуйте пройти что-нибудь, кроме числа в нашем Calculatearea
Функция сейчас и поток отправит нам удобное сообщение:
Теперь мы гарантируем, что функция когда-либо примет только в качестве входных данных, и возвращает допустимый номер в качестве вывода.
Поскольку проверяют тип типа, когда вы кодируете ошибки, когда вы кодируете, это намного удобнее (и намного дешевле), чем узнать об ошибке после того, как код был отправлен вашим клиентам.
Преимущество № 2: Вы получаете живую документацию
Типы служат живой, дыхательной документацией для себя, так и для других пользователей нашего кода.
Чтобы посмотреть, как, давайте посмотрим на этот метод, который я когда-то нашел в большой кодовой базе, в которой я работал:
На первый взгляд (и второй и третий) я понятия не имел, как использовать эту функцию.
Цитата A Номер
? Или логический
? Это способ оплаты AN объект
? Или, может быть, это строка
Представляя тип способа оплаты? Функция возвращает дату как строка
? Или как Дата
объект?
Нет подсказки.
Мое решение в то время было оценить бизнес-логику и GREP через кодовую базу, пока я не подумал его, но это много работы, просто чтобы понять, как работает простая функция.
С другой стороны, если мы написали что-то вроде:
Становится немедленно очистить, какие данные данных функция принимает в качестве ввода, а какие данные он возвращается в качестве вывода. Это демонстрирует, как мы можем использовать статические типы для связи намерение функции. Мы можем сказать другим разработчикам то, что мы ожидаем от них, и можем видеть, что они ожидают от нас. В следующий раз, когда кто-то будет использовать эту функцию, не будет вопросов.
Существует аргумент, который должен быть сделан, что добавление кода комментариев или документация может решить ту же проблему:
Это работает. Но это больше многословного. Помимо извлеченности, кодовые комментарии, как это трудно поддерживать, потому что они ненадежны и отсутствуют структура – некоторые разработчики могут написать хорошие комментарии, некоторые могут писать неясные комментарии, а некоторые могут забыть их вообще.
Особенно легко забыть обновить их при рефакторе. Тип аннотаций, однако, имеют определенный синтаксис и структуру и никогда не смогут устареть – они кодируются в код.
Преимущество № 3: это уменьшает запутанную обработку ошибок
Типы помогают удалить запутанную обработку ошибок. Давайте пересмотрим нашу Calculatearea
Функция, чтобы увидеть, как.
На этот раз я возьму на себя массив радиусов и рассчитал область для каждого радиуса:
Эта функция работает, но не правильно обрабатывает недействительные аргументы ввода. Если мы хотели убедиться, что мы правильно обрабатываем случаи, когда вход не является действительным массивом номеров, мы получим функцию, которая выглядит как:
Ух ты. Это много кода для немного функциональности.
Но со статическими типами мы могли бы просто сделать:
Теперь функция на самом деле выглядит так, какая она изначально выглядела без всякого визуального беспорядка от обработки ошибок.
Достаточно легко, чтобы увидеть выгоду, верно?:)
Преимущество № 4: Вы можете рефакторировать с большей уверенностью
Я объясню это через Anecdote: я работал в очень большой кодовой базе один раз, и был метод, определенный на Пользователь
Класс, который нам нужно было обновить – специально, нам нужно было изменить одну из параметров функций из строка
к объект
Отказ
Я сделал изменение, но имел холодные ноги для совершения изменений – настолько много вызовов этой функции, посыпанной по кодовой базе, что я понятия не имел, если бы я правильно обновил все экземпляры. Что, если я пропустил несколько вызовов глубоко в некоторых непроверенных помощниках?
Единственный способ узнать, было отправить код и молиться, чтобы оно не взорвалось с ошибками.
Использование статических типов, избегала бы этого. Это дало бы мне уверенность и спокойствие, что если я обновил функцию и в свою очередь, обновила определения типа, проверяют тип типа для меня, чтобы поймать все ошибки, которые я пропустил. Все, что мне придется сделать, это пройти через эти ошибки типа и исправить их.
Преимущество № 5: он отделяет данные из поведения
Осталось меньше разговоров – о пользе статических типов заключается в том, что они помогают отделить данные поведения.
Давайте пересмотрим нашу Calculateareas
Функция со статическими типами:
Подумайте, как мы пойдем о составлении этой функции. Поскольку мы аннотирующие типы, мы вынуждены сначала подумать о типе данных, которые мы собираемся использовать, чтобы мы могли соответственно определить входные и выводы.
Только тогда мы реализуем логику:
Эта способность точно выражать данные, отдельные из поведения, позволяет нам быть явным по поводу наших предположений и точнее передать наше намерение, что облегчает некоторую умственную нагрузку и приносит некоторую умную четкость программиру. Без этого мы остались отслеживать это мысленно в некотором роде.
Преимущество № 6: это устраняет всю категорию ошибок
Одним из наиболее распространенных ошибок или ошибок, которые мы сталкиваемся с разработчиками JavaScript, являются ошибками в типе во время выполнения.
Например, скажем, наше начальное состояние приложения определяется как:
И давайте предположим, что мы сделаем вызов API, чтобы получить сообщения, чтобы заполнить наши appstate
Отказ Далее наше приложение имеет чрезвычайно упрощенный компонент просмотра, который занимается Сообщения
(Определяется в нашем состоянии) в качестве опоры и отображает непрочитанное количество и каждое сообщение в виде элемента списка:
Если вызов API для получения сообщений не удается или возвращает undefined
Мы бы в конечном итоге с ошибкой типа в производстве:
TypeError: не может прочитать свойство «Длина» неопределенных
… И ваша программа вылетает. Вы теряете клиента. Баммер
Давайте посмотрим, как типы могут помочь нам. Мы начнем с добавления типов потоков в наше состояние приложения. Я набрал псевдоним Appstate
а затем используйте это, чтобы определить состояние:
Поскольку наша API для извлечения сообщений известна, что она ненадежна, здесь мы говорим, что Сообщения
это Может быть
Тип массива строк.
Та же дело, что и в прошлый раз – мы принесем наши сообщения от ненадежных API и используем его в нашем компоненте просмотра:
За исключением сейчас, поток будет поймать нашу ошибку и жаловаться:
WHOA BUDDY!
Потому что мы определили Сообщения
как Может быть
Тип, мы говорим, что разрешено быть null
или undefined
Отказ Но это до сих пор не позволяет нам выполнять операции на нем (например .LENGHING
ИЛИ .map
), не делая null
Проверьте, потому что если Сообщения
Значение было на самом деле null
или undefined
Мы получим ошибку типа, если мы выполним любую операцию на нем.
Итак, давайте вернемся и обновите нашу функцию просмотра, чтобы быть что-то вроде:
Поток теперь знает, что мы обрабатывали случай, когда сообщения это null
или undefined
Итак, тип кода проверяет 0 ошибок. Длинные мертвые ошибки типа выполнения:)
Преимущество № 7: это уменьшает количество модульных тестов
Ранее мы видели, как статические типы могут помочь устранить запутанную обработку ошибок, поскольку они гарантируют вводные и выводы. В результате они также уменьшают количество узлов.
Например, давайте вернемся к нашим динамически набранным Calculateareas
Функция с обработкой ошибок:
Если бы мы были усердными программистами, мы могли бы подумать о тестировании неверных входов, чтобы убедиться, что они правильно обрабатываются в нашей программе:
… и так далее. За исключением того, что я очень вероятно, что мы забываем проверить некоторые краевые случаи – тогда наш клиент – это то, что обнаруживает проблему.:(
Поскольку тесты исключительно на основе случаев, которые мы думаем о тестировании, они экзистенны и легко обойтись.
С другой стороны, когда мы обязаны определить типы:
… не только мы гарантируем, что наше намерение соответствует реальности, но они также просто сложнее сбежать. В отличие от эмпирически на основе тестов, типы являются универсальными и трудно быть умывательными.
Большая картина здесь: тесты великолепны при тестировании логики, а типы при тестировании типов данных. При комбинировании сумма частей больше всего.
Преимущество № 8: он предоставляет инструмент моделирования домена
Одним из моих любимых случаев использования для типов является моделирование домена. Модель домена представляет собой концептуальную модель домена, которая включает в себя как данные, так и поведение на эти данные. Лучший способ понять, как вы можете использовать типы для демонстрации домена, посмотрев на пример.
Допустим, у меня есть приложение, в котором пользователь имеет один или несколько способов оплаты для совершения покупок на платформе. Существует три типа способов оплаты, им разрешено иметь (PayPal, кредитные карты, банковский счет).
Итак, мы впервые примем псевдоним этих трех разных типов способа оплаты:
Теперь мы можем определить наши Срок оплаты Method
Тип как непересекающийся союз с тремя случаями:
Далее, давайте сможем моделировать наше состояние приложения. Чтобы сохранить его простым, давайте предположим, что наши данные приложений состоят только из способов оплаты пользователей.
Это достаточно хорошо? Ну, мы знаем, что чтобы получить методы оплаты пользователя, нам нужно сделать запрос API, и в зависимости от того, где в процессе выбора мы есть, наше приложение будет иметь разные состояния. Так что на самом деле есть четыре возможных состояния:
1) мы не получили методы оплаты 2), мы выбираем способы оплаты 3), мы успешно получили методы оплаты 4), мы попробовали вытеснять, но произошла ошибка метода оплаты
Но наш простой Модель
Тип с Срок оговорки
не покрывает все эти случаи. Вместо этого предполагает, что Срок оговорки
всегда существует.
Хм. Есть ли способ моделировать наше состояние приложения, чтобы быть одним из этих четырех случаев, и только эти четыре случая? Давайте взглянем:
Мы использовали неразмерный тип Union, чтобы определить наше состояние как один из четырех сценариев, описанных выше. Обратите внимание, как я использую Тип
свойство, чтобы определить, в каком из четырех состояний наше приложение в. Это Тип
Собственность на самом деле то, что делает это несерьезным союзом. Используя это, мы можем сделать анализ случая, чтобы определить, когда у нас есть методы оплаты, а когда мы этого не сделаем.
Вы также заметите, что пропустите общий тип Е
и D
в состояние приложения. Тип D
будет представлять метод оплаты пользователя ( Paymentmethod
определено выше). Мы не определены типа Е
, который будет нашим типом ошибки, поэтому давайте сделаем это сейчас:
Теперь мы можем моделировать наш домен приложения как:
Таким образом, подпись для нашего приложения State теперь AppState
W
Здесь E имеет Форма HTT
Perro R
и D платеж
Метод Отказ И AP
У Pstate есть четыре (и только эти четыре) возможные ST ATES: Notf
et Ched, Fe
TC Hing, f
Ailur E и S
uccess.
Я нахожу этот тип моделирования домена, полезной для мышления и построения пользовательских интерфейсов против определенных бизнес-правил. Бизнес-правила рассказывает нам, что наше приложение может когда-либо быть в одном из этих государств. Таким образом, это позволяет нам явно представлять создание нашего приложения и гарантирует, что он когда-либо будет в одном из заранее определенных государств. И когда мы создаем эту модель (например, для создания компонента просмотра), он наступает вописно очевидно, что нам нужно обрабатывать все четыре возможных состояния.
Более того, код станет самообязативным – вы можете посмотреть в случаи профсоюза и немедленно выяснить, как структурировано состояние приложения.
Недостатки использования статических типов
Как и все остальное в жизни и программировании, проверка статического типа поставляется с его компромиссами.
Важно, чтобы мы понимаем и признаем их, чтобы мы могли принять обоснованное решение, когда статические типы имеют смысл, и когда они просто не стоят этого.
Вот несколько из этих соображений:
Недостатком № 1: Статические типы требуют инвестиционной аванс для изучения
Одной из причин JavaScript является таком фантастическим языком для начинающих, заключается в том, что он не требует, чтобы ученик узнал целую систему типа, прежде чем они могут быть продуктивными на языке.
Когда я изначально изучал ELM (статически набранный функциональный язык), типы часто попали в путь. Я бы постоянно столкнулся с ошибками компилятора, связанных с определениями моих типов.
Обучение того, как использовать систему типа, эффективно прошел половину битвы в изучении самого языка. В результате статические типы сделали кривую обучения для ELM Cootper, чем для JavaScript.
Это важно, особенно для начинающих, где когнитивная нагрузка синтаксиса обучения на всех временах высоко. Добавление типов на смесь может сокрушить новичок.
Недостаток № 2: Verbousity может болотиться
Статические типы часто делают программы выглядеть более многослойными и загроможденными.
Например, вместо:
Мы должны были написать:
И вместо:
Мы должны были написать:
Очевидно, что это может добавить дополнительные строки кода. Но есть пара аргументов против этого, будучи настоящим недостатком.
Во-первых, как мы упоминали ранее, статические типы помогают устранить всю категорию тестов. Некоторые разработчики будут рассмотреть это совершенно разумным компромиссом.
Во-вторых, как мы увидели ранее, статические типы иногда могут устранить запутанную обработку ошибок, и в свою очередь, значительно уменьшают визуальный беспорядок.
Трудно сказать, является ли многообразие реальным аргументом против типах, но это стоит помнить.
Недостаток № 3: Типы найдите время для мастера
Требуется время и много практики, чтобы узнать, как лучше указать типы в программе. Более того, разрабатывая хороший смысл для того, что стоит отслеживать статически и что удерживать динамику, также требует тщательной мысли, практики и опыта.
Например, один подход, который мы могли бы принять, – это кодировать критическую бизнес-логику с типами, оставляя недолговечные или неважные кусочки логики динамики, чтобы избежать ненужной сложности.
Это различие может быть трудно сделать, особенно когда разработчики менее опытные с типами, вызывают суждение призыв к лету.
Недостаток № 4: Статические типы могут удерживать быстрое развитие
Как я уже упоминал ранее, типы немного подталкивали меня, когда я изучал ELM – особенно при добавлении кода или внесения изменений. Постоянно отвлекается на ошибки компилятора, затрудняли почувствовать, что я делал какой-либо прогресс.
Аргумент здесь состоит в том, что проверка статического типа может привести к тому, что программатор проиграл фокус слишком часто – и, как мы знаем, фокус является ключом для написания хороших программ.
Не только то, но шашки статического типа не всегда идеальны. Иногда вы столкнулись с ситуациями, где вы знаете, что вам нужно сделать, и проверка типа просто мешает.
Я уверен, что есть другие компромиссы, я скучаю, но это были большие для меня.
Далее, окончательный вывод
В Окончательный раздел , мы сделаем заключение, обсудив, имеет ли смысл использовать статические типы.
Увидимся Там Отказ