company_banner

Как перенести на TypeScript большую кодовую базу React UI-компонентов

    Привет! Меня зовут Иван Греков, я работаю UI-разработчиком в frontend-команде Badoo. Главные задачи нашей команды — создание новых и поддержка существующих пользовательских интерфейсов для сайтов и приложений Badoo и Bumble. 

    Когда в конце 2019 года мы начали параллельно работать над несколькими проектами, мы задумались над повышением стабильности кода и возможностью его многократного использования. Для этого мы решили переписать наши 630 React UI-компонентов на TypeScript. Я расскажу о том, как мы работали над ними без перерыва в доставке фич и как организовали поэтапный переход на TypeScript для UI-разработчиков, которым этот язык был в новинку.

    Почему мы решились на переход

    К началу проекта мы уже отделили бизнес-логику от UI-компонентов: это очень помогло нам при поддержке кода приложений. Когда мы начали создавать общие модули с бизнес-логикой, JS-разработчики из команды фронтенда сразу писали их на TypeScript, чтобы обеспечить типобезопасность (type safety). 

    Наша UI-команда тоже решила применить этот подход, так как хорошо понимала его преимущества.

    • Типобезопасность наших UI-компонентов. Качество продакшен-кода улучшается, если мы проверяем типы при сборке, а не в среде выполнения. В большинстве наших приложений и проектов на основе React уже использовались prop-types. Но главная проблема заключалась в том, что проверки типов в prop-types не выполнялись принудительно при сборке и упаковке приложений. И если кто-то менял API или тип одного из компонентов, это могло оказаться критическим изменением и привести к рассинхронизации типов компонентов на разных уровнях с возникновением багов или предупреждений.

    • Единство кодовой базы на TypeScript. Благодаря этому на написание и проверку кода тратится меньше времени: после создания компонента можно его многократно использовать в разных проектах.

    Главными целями нашего проекта стали более высокая надёжность приложений и предсказуемость процесса написания кода.

    С чего мы начинали

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

    Мы разделили бизнес-логику и UI-представление в соответствии с архитектурным подходом, принятым нами для фронтенда. У нас есть два типа компонентов:

    • контейнеры, которые представляют бизнес-логику на JavaScript;

    • UI-компоненты, написанные как stateless функции. 

    Это помогает нам писать и рефакторить UI-компоненты, не трогая бизнес-логику, и заодно даёт прекрасную возможность экспериментировать и сопровождать код без помех разработке фич.

    В нашей UI-команде пять разработчиков, которые специализируются на создании пользовательских интерфейсов. Все они, включая меня, опытные фронтендеры, умеющие работать с JavaScript и React.js. Однако многие из нас до этого либо не работали с TypeScript, либо только начинали с ним знакомиться. Поэтому мы поставили себе ещё одну цель: помочь коллегам набраться опыта и привести минимальный уровень владения TypeScript в команде к единому знаменателю.

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

    Мы сосредоточились на нескольких ключевых направлениях: коде, процессе и команде. Когда я планировал проект и размышлял о том, как организовать работу по всем направлениям, я нашёл подходящую управленческую стратегию — PDCA (Plan-Do-Сheck-Act). Это алгоритм принятия решений: сначала планирование, потом действие, затем проверка и корректировка действия. По этой схеме я и начал действовать: оценил состояние кодовой базы, затем спланировал работу, оценивал прогресс и подводил итоги.

    Состояние кодовой базы

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

    Объём кода

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

    В середине января в кодовой базе было 554 JSX-файла, из которых 227 — компоненты и 227 — относящиеся к компонентам файлы спецификаций с VRT-тестами. На тот момент мы перевели на TypeScript 62 компонента и 62 теста.

    Эти данные — показатель прозрачности работы команды: можно каждую неделю измерять, как продвигается проект, и сравнивать прогресс с нашими ожиданиями. Мы назначили оценку на середину пятницы, потому что в другие дни у нас обычно бывает по два релиза, а в пятницу — только один, утром. Так что в этот день мы могли оценить объём переведённых и отправленных в эксплуатацию компонентов. 

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

    Покрытие тестами

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

    В подобных проектах особенно полезны визуальные регрессионные тесты. Они помогают сосредоточиться на функциональности тестирования, а благодаря стабильности покрытия мы тратим на визуальные тесты меньше ресурсов. Например, если у компонента три разных состояния, то мы покрываем их тремя отдельными тестами. Так, на начало проекта у нас было около 2000 тестов.

    Планирование

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

    Начнём с анализа кода.

    Анализ графа зависимостей

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

    Прежде чем начинать работу с кодом, нужно выявить его внутренние взаимосвязи. Нужно понять, какие компоненты созависимы, и в зависимости от этого установить порядок переработки компонентов. Для этого мы построили граф зависимостей с помощью инструмента madge, который строит графы на основе структуры проекта. Для нас было важно, что madge умеет строить и на основе webpack-конфигурации. У этого инструмента много настроек, помогающих создавать правильные схемы.

    Построив граф, мы начали переводить на TypeScript компоненты, которые расположены в правой части: у них нет или очень мало зависимостей.

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

    Мы каждую неделю обновляли граф и пересматривали очередь на перевод в TypeScript. Каждую пятницу оставалось всё меньше зависимостей и компонентов. Граф был хорошей иллюстрацией прогресса и источником данных для принятия решений, если мы начинали буксовать.

    Оценка сложности компонентов

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

    Для этого мы пометили компоненты тегами. Использовали следующие теги соглашений и фильтрации:

    • TS basic — для компонентов с простым и понятным интерфейсом, а также с отсутствием или минимальным количеством зависимостей;

    • TS component — для средних компонентов, у которых достаточно понятный интерфейс и минимальное количество зависимостей;

    • TS view — для сложных компонентов с составным интерфейсом и значительным количеством зависимостей.

    С учётом уровня владения TypeScript и своего прогресса в обучении разработчики начинают с базовых компонентов и постепенно переходят к более сложным. Мы договорились, что сначала я буду ставить задачи разработчикам. А по мере того как они будут осваиваться, они будут становиться более независимыми. В конечном итоге коллеги начали работать с задачами самостоятельно.

    Планируя работу, нужно держать в голове дополнительные вопросы о сложности компонентов. Можно ли перевести конкретный компонент автоматически? Хранит ли он состояние? Есть ли в его типе перечисление (Enum) или объединение (Union)? Нужно ли поменять его тип или написать новый?

    Разбивка проекта на этапы

    Учитывая сложность и масштаб проекта, а также размер команды, вы можете разделить проект на фрагменты с разным количеством компонентов. Мне было удобно каждую неделю оценивать прогресс на основе релизных циклов. Но это можно делать и раз в две недели, и раз в месяц. Я предпочитал использовать диаграммы Ганта и регулярно отслеживать, сколько времени потрачено на проект: это помогало сохранять высокий уровень прозрачности и качественно отчитываться перед руководством.

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

    Этап 0 — создание базы знаний команды

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

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

    Мы добавили в базу знаний рекомендации и информацию по разным темам:

    • конфликты типов с инлайненными CSS-стилями, если они определены как отдельные константы или объекты;

    • использование глобальных компонентов, которые не импортируются и не используются в свойствах внутри компонентов;

    • использование нескольких Enums в одном с набором ключей для первых значений во всех Enums;

    • использование объединения для массива из заранее определённых массивов значений.

    Один из главных пунктов - соглашения по стилю кода. Перед началом работы мы унифицировали их во всех проектах и приняли единый набор инструментов для JS-файлов: ESLint и Prettier. До этого мы могли писать разный код, но теперь мы привели его к единому стилю. Это очень помогло при переходе на TypeScript. А поскольку стиль автоматически проверялся перед коммитами, это не увеличивало сложность и не требовало от разработчиков больше времени.

    Этап 1 — подготовка обучения

    Мы предоставили всем участникам список вводных материалов для ознакомления. После того как люди в удобном для них темпе (параллельно с работой над другими проектами) прошли вводную часть, они получили свои первые задачи. Мы начали с TypeScript-компонентов, помеченных тегом basic.

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

    Совет: делегируйте задачи, отслеживайте прогресс

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

    А теперь пора переходить к коду.

    Оценка прогресса

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

    Используйте измеримые показатели

    Это очевидно, но напомню, что качество коммуникации зависит от прозрачности процесса реализации проекта. А её можно достичь, оперируя показателями, которые понятны и участникам команды, и руководству. В нашем проекте мы использовали такие метрики:

    • покрытие кодовой базы в продакшене — доля кода на TypeScript;

    • вовлечённость UI-разработчиков — сколько участников команды знакомы с технологией и используют её;

    • темп работы — сколько задач разработчики выпустили за период.

    Коммуникация внутри команды

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

    Обновляйте соглашения

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

    Регулярные отчёты

    Управляя проектом, важно постоянно сравнивать показатели и держать руку на пульсе.

    Я уже упоминал инструменты madge и cloc, с помощью которых мы проводили первичную оценку кодовой базы. Но ещё с их помощью я еженедельно собирал данные, чтобы оценить, как продвигается работа. Мы видели, насколько быстро движется команда и каждый из нас в отдельности. Иногда важно остановиться и подумать: как я могу повлиять на показатели? всё ли хорошо или нужно ускориться? как нам это сделать? Ответы на эти вопросы помогали мне сохранять прозрачность работы над проектом.

    Результаты

    Мы закончили работу примерно через три месяца. В результате все наши разработчики освоили TypeScript и теперь пишут на нём новые компоненты.

    Благодаря распределению задач мы смогли выделить для команды время между написанием нового кода и переписыванием старого. Еженедельно мы перебалансировали набор задач для каждого разработчика.

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

    Команда успешно освоила язык

    Одними из главных задач были освоение TypeScript командой и создание общей базы знаний об этой технологии. Теперь уровень навыков внутри команды сравнялся и все участники пишут на TypeScript.

    Полностью прозрачный процесс

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

    Более надёжная и быстрая разработка

    Поскольку теперь мы вылавливаем определённые ошибки на стадии сборки, а не на стадии QA и не в проде, процесс разработки изменился в лучшую сторону. А благодаря использованию Prettier и ESLint перед коммитом разработчики просто не могут совершать крупные распространённые ошибки, которые приводят к отказу функциональности приложений.

    Совет: выбирайте правильные инструменты

    Каждый разработчик вправе сам выбирать набор инструментов для работы над проектом. Однако хочу дать совет: выбирайте транспиляторы, кодмоды и сниппеты. Например, расширение VSCode компании Lyft позволяет в один клик переименовывать файлы и переносить в TypeScript структуры и типы React-компонентов. Оно поддерживает React начиная с версии 16.3.14 и до 16.4.0, его можно настроить таким образом, чтобы оно поддерживало и более новый синтаксис. Хотя на момент написания статьи расширение находится в архиве, оно прекрасно выполняет свои функции.

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

    Этот совет применим к любому масштабному процессу миграции в сфере фронтенда.

    Список свежих статей о React и TypeScript

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

    О выборе между JavaScript и TypeScript:

    1. Choosing Between TypeScript vs JavaScript: Technology, Popularity

    2. How TypeScript is making programming better

    3. The TypeScript Tax

    О том, как настроить TypeScript:

    1. How does TypeScript work? The bird’s eye view

    2. Creating web apps via TypeScript and webpack

    3. Set Up a Typescript React Redux Project

    4. React TypeScript: Basics and Best Practices

    5. Setting TypeScript For Modern React Projects Using Webpack

    6. Setting up efficient workflows with ESLint, Prettier and TypeScript

    7. The Practical Guide to Start React Testing Library with TypeScript.

    О переводе на TypeScript имеющейся кодовой базы React:

    1. How to move your project to TypeScript — at your own pace

    2. How to Easily Migrate From JavaScript to TypeScript

    3. Gradually using TypeScript in Your React Project

    4. Porting to TypeScript Solved Our API Woes

    5. How to Migrate a React App to TypeScript

    6. Convert Your Javascript React App to TypeScript, the Easy Guide

    7. TypeScript and React

    8. Using TypeScript with React

    9. The Great CoffeeScript to Typescript Migration of 2017

    10. 12 советов по внедрению TypeScript в React-приложениях

    О том, как писать на TypeScript новую кодовую базу React:

    1. Build a Tic Tac Toe App with TypeScript, React and Mocha

    2. A Practical Guide to TypeScript — How to Build a Pokedex App Using HTML, CSS, and TypeScript

    3. Create a React component library with TypeScript and Storybook

    4. How To Build a Customer List Management App with React and TypeScript

    5. Using TypeScript in Grommet Applications

    Для более глубокого изучения TypeScript:

    1. TypeScript Best Practices — Useless Interfaces, Classes, and Promises

    2. React with TypeScript: Best Practices

    3. Great import schism: Typescript confusion around imports explained

    4. Разница между типом и интерфейсом в TypeScript

    Badoo
    Big Dating

    Похожие публикации

    Комментарии 15

      +1
      Подход впечатляет.
      Как удалось договориться с бизнесом о необходимости перехода?
      Сильно ли повлияло это мероприятие на регулярность доставки фич?

      По моему опыту получить ресурсы на подобное мероприятие очень непросто, ибо «а кто будет фичи пилить, у нас вон сколько всего на подходе». В итоге получается жонглирование вприсядку. Похожую вещь тоже делали, но очень размазанно по времени (когда было окно в потоке фич) и без такого четкого плана.
        0
        Спасибо!

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

        Что касается доставки фичей — за счет распределения задач мы не замедляли темпы: пока часть команды занималась продуктовыми задачами м сразу писали код на typescript, а другая часть команды — переводила код на TypeScript. Грамотный баланс в данном случае достигался за счет планирования нагрузки и еженедельной оценки прогресса. C технической точки зрения в любой момент любого участник проекта мог переключить на другие задачи, остановить процесс перевода и возобновить работу, когда появлялось время.

        Также мы изначально выделили время на техническое планирование, чтобы сразу определить, насколько можно разделить проекты на этапы и впоследствии изолировано выполнять их.
          0
          Значит у вас не было перегрузки, как и должно быть в норме
        –4
        что позволило нам ускорить работу над проектами.

        поржал…

        Нахуя вы это все делали? Зачем нужен TS в ui компонентах и в принципе на фронте? (кто будет минусить — просьба обосновать в комментах)
          0
          Если делаешь что-то сложнее туду-листа, то у TS сплошные преимущества
            +1
            Так разве не для этого все разбивается на небольшие компоненты, чтобы из них можно было собрать хоть туду-лист, хоть космодром? Поддерживаю ответившего выше, про «ускорить разработку» заявление сомнительное. Prop-types обычно хватает за глаза.
              +3
              Попробую рассказать подробнее про ускорение разработки на TypeScript и про Prop-types в React UI компонентах :)

              Сразу скажу, что примеры будут из личного опыта, полученного на проектах разного масштаба и в различных командах.

              Prop-types — это проверка в run-time. То есть, чтобы проверить, что интерфейс компонента актуален при внесении изменений в ветку у нас есть, как минимум, 2 стратегии:

              1) открыть браузер и проверить в консоли каждую страницу. Если мы поменяли интерфейс базового компонента и он используется в 100 страницах? Или для показа компонента надо будет выполнить определенные условия (кликнуть на третьем экране вниз, загрузить фото, ввести пароль). Это будет очень затратно по времени. Это становится явной проблемой, когда необходимо поддерживать и обновлять UI-библиотеки на средних и больших проектах.
              2) Запустить песочницу/библиотеку компонентов с документацией. Допустим, что у нас все компоненты и их интерфейсы видны и описаны и их можно проверить либо руками, либо через visual regression tests сравнить изменения. Это может быть быстрее первого способа, но все равно займет какое-то время и не гарантирует однозначного результата.
              Оффтоп про конлфикты типов в UI компонентах
              Тут можно подробнее углубиться в конфликты типов при отображении UI компонентов, если будет интересно, то отдельно приведу примеры.


              Если интерфейс компонента на TypeScript, то проверка на типы будет при сборке проекта и также по запросу введением одной команды в консоли. Мы сразу получаем все возможные конфликты и проблемы в отчете проверки при автоматическом проходе по всем компонентам. Это самый быстрый способ. Это ощущается и в масштабе, когда один разработчик работает над проектом и когда в команде 10+ разработчиков, которые параллельно доставляют различные фичи.

              Априори мы исходим из того, что проверка типов при разработке — это минимальная и быстрая проверка на явные баги. А так как эта проверка в TypeScript работает сразу из коробки — мы снижаем нагрузку на разработчиков и у нас появляется больше времени на разработку нового функционала, так как цикл разработки ускоряется без риска потери качества.

              Более детальный пример — это проверка типов при конфликтах веток. Решение конфликтов занимает меньше времени за счет автоматической проверки и всплывающих подсказок в редакторах. В обоих примерах смена типов также может быть автоматизирована.

              И главный момент — Prop-types не гарантирует строго соблюдения правил.
              Явный пример

              Казалось бы — в текущем примере мы ничего не испортили. Потому как внутри UI компонента простой render. Однако если в компоненте были какие-то изменения текста — убирания пробелов, строка с большой буквы), то в этом случае мы потратим значительное время на проверку типов или рискуем пропустить код с ошибкой на Production. А в случае с TypeScript — мы в момент сборки знаем о проблеме


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

              Конечно, внедрение TypeScript потребует определенного времени для команды, но это уже другой аспект, который я уже описал в статье)
                +1
                Вот это уже по делу, спасибо! Но все равно не увидел прям сильных преимуществ, особенно в скорости разработки.
                  0
                  особенно в скорости разработки

                  Так а выигрыша и нет. Динамическая типизация всегда будет выигрывать в скорости разработки против статической. Автор заблуждается, добровольно или нет — неясно.
              0
              Спасибо «кэп»! По делу есть что сказать?
              0
              Зачем нужен TS в ui компонентах и в принципе на фронте?
              Типизированные payload в Redux и сигнатуры DispatchProps в компонентах, например. Гораздо удобнее посмотреть всё в подсказках IDE, чем идти и читать, что и в каком формате где-то отдаётся.
              +1
              Возможно я в начале резко выразился, кто-то меня понял, кто-то увы… Я не против TS и не бомблю против/за него, как некоторые… Сам его использую. Отсюда у меня и возник вопрос. Кого не спроси — ну это же типизация(это круто, модно)… и на этом все, никаких аргументов нормальных…
                0
                Поздравляю, Вы не зашоренный, как многие ). Многие выбирают TS лишь по причине модности, а потом начинают выдумывать причины, чтобы его заюзать в проекте. Несколько лет назад, до широкого распространения ES6 он действительно был приятней в использовании ES5. На данный момент преимуществ у практически TS и не осталось. Но есть одна причина, иногда весьма существенная — за счет статической типизации он позволяет прилично сократить количество ошибок у слабых разработчиков. Если проект большой, тим лид также не силен(или нет времени), а подобных персонажей много — то выгода очевидна.
                  0
                  за счет статической типизации он позволяет прилично сократить количество ошибок у слабых разработчиков
                  Когда-то я слышал то же самое про языки с отсутствием прямой работы с памятью, мол, настоящие профессионалы ошибки с двойным разыменовыванием указателей и выходом за пределы массивов не допускают. Что, конечно, полная чушь. Чем больше язык даёт пространства для допуска ошибок, тем больше этих ошибок будет, уровень квалификации тут роли не играет.

                  Динамическая типизация всегда будет выигрывать в скорости разработки против статической.
                  А вы пользуетесь IDE?
                    +1
                    А вы пользуетесь IDE?

                    Нет конечно, на бересте все еще пишу.

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

              Самое читаемое