<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>ru</language>
    <title>Scala</title>
    <description/>
    <link>https://tproger.ru/tag/scala</link>
    <atom:link href="https://tproger.ru/tag/scala/feed" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Tue, 29 Sep 2026 07:25:32 GMT</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>12</sy:updateFrequency>
    <image>
      <title>Scala</title>
      <link>https://tproger.ru</link>
      <url>https://tproger.ru/apple-touch-icon.png</url>
    </image>
    <item>
      <title>Почему главные конфликты в разработке не связаны с технологиями</title>
      <link>https://tproger.ru/articles/pochemu-glavnye-konflikty-v-razrabotke-ne-svyazany-s-tehnologiyami</link>
      <comments>https://tproger.ru/articles/pochemu-glavnye-konflikty-v-razrabotke-ne-svyazany-s-tehnologiyami?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Андрей Козлов]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/pochemu-glavnye-konflikty-v-razrabotke-ne-svyazany-s-tehnologiyami</guid>
      <description><![CDATA[<p>Почему конфликты в IT-командах возникают не из-за технологий, а из-за коммуникации, идентичности и инженерной культуры. Разбор споров вокруг Scala, Kotlin, архитектуры, технического долга и командной динамики в разработке.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/pochemu-glavnye-konflikty-v-razrabotke-ne-svyazany-s-tehnologiyami">Почему главные конфликты в разработке не связаны с технологиями</a>»</p>]]></description>
      <category><![CDATA[Алгоритмы и структуры данных]]></category>
      <category><![CDATA[Функциональное программирование]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[Kotlin]]></category>
      <category><![CDATA[Тимлид]]></category>
      <category><![CDATA[Lego]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 15 May 2026 06:19:51 GMT</pubDate>
      <content:encoded><![CDATA[<p>В первый месяц работы юный разработчик может думать, что причина конфликтов в команде скрывается в технологических нюансах. Через год он начинает подозревать: дело в чем-то другом. Десять лет спустя он с уверенностью скажет: технологии здесь вообще ни при чем.</p><h2>Инструмент как часть личности</h2><p>Возьмем типичную ситуацию: переход на новый стек или поддержка старой базы. Допустим, команда третью неделю (а иногда и третий месяц!) обсуждает, оставить Scala или перейти на Kotlin. Аргументы обеих сторон озвучиваются на первой же встрече, а затем просто повторяются от созвона к созвону. Кто-то говорит об экосистеме, кто-то — о кривой обучения. Внешне это выглядит как техническая дискуссия, но решение не принимается.</p><p>За годы работы с инженерными командами я заметил закономерность: чем дольше тянется спор, тем меньше в нем остается от сути технологий. Люди спорят о синтаксисе, но неозвученная дискуссия идет о том, чья экспертиза весит больше, чья позиция будет услышана и кто в итоге будет нести ответственность.</p><p>Программист, который пять лет пишет на Scala, не просто использует инструмент. Язык стал частью его мышления: как он декомпозирует задачи и выстраивает архитектуру. И когда кто-то предлагает перейти на Kotlin, человек слышит: «То, что ты умеешь, больше не нужно». Отсюда и высокий градус эмоций. Годы практики делают стек частью профессиональной идентичности. Оспорить выбор инструмента — значит задеть человека лично.</p><h2>Ловушка единомышленников</h2><p>Отдельная история — когда вся команда пришла из одной среды. Если вы учились в одном вузе, слушали тех же спикеров и одновременно осваивали стек — на старте это кажется преимуществом. Вы понимаете друг друга с полуслова.</p><p>Однако со временем команда перестает замечать собственные слепые пятна. Любой «человек со стороны» с его новым взглядом воспринимается как дилетант, пытающийся найти изъяны в идеальной системе. Холивары в таких коллективах особенно вязкие: все одинаково уверены, что «очевидное очевидно», а любое альтернативное мнение априори ошибочно или упоминается лишь в контексте «идея хорошая, но делать ее мы не будем».</p><h2>Скульптура против Lego: конфликт ценностей</h2><p>В инженерной культуре сложность часто путают с качеством. Из-за этого возникают одни из самых затяжных конфликтов: когда один разработчик ратует за лаконичность и скорость, а другой — за «высокую архитектуру». Scala появилась именно из этой логики: язык создавался людьми, которые хотели объединить объектно-ориентированное и функциональное программирование в одном инструменте. Получилось мощно и академически красиво, но взаправду сложно. И вопрос, а всегда ли нужно вот настолько сложно, тоже порождает споры.</p><p>Хорошая аналогия — скульптура из мрамора против фигурки из Lego. Когда мы видим работы Страцца и Бернини, которые смогли передать в камне эффект тончайшей вуали, мы застываем в восхищении посреди музея. Но создание таких статуй требовало времени, а внести “правки от заказчика” означало бы подвергнуть риску всю работу: попробуйте исправить скол на мраморной статуе, которую ваяли сильно дольше, чем планировалось. В случае с конструкцией из Lego все намного проще: вынул блок, вставил другой, и вот из фигурки кошки уже получился «Тысячелетний сокол».</p><p>Чем сложнее язык или технология, тем глубже оказываются ошибки и тем труднее их потом найти. Причем платит за это не только тот, кто писал. Автор ошибки как раз легко может к этому моменту уже уйти на повышение. Но каждый следующий человек, который начнет взаимодействовать с этим кодом, заплатит ту же цену. Технический долг в командах почти всегда описывают одинаково: «это то, что написали до меня». Мы сильно реже склонны упоминать его, имея в виду собственный код и свои планы. Сложные решения, выбранные ради красоты концепции, — один из самых надежных способов создать именно такой долг.</p><p>Сложный инструмент — не приговор. Но когда его выбирают ради престижа, а не задачи, споры вокруг него становятся особенно изматывающими.</p><h2>Конфликт как трудности перевода</h2><p>Важная вещь, которую часто пропускают: разные люди воспринимают одно и то же взаимодействие по-разному. Для одних горячий спор — нормальный способ думать вслух и нащупывать решение. Для других тот же разговор выглядит как конфликт, который нужно срочно разрядить или который надо зарепортить, тимлиду или сразу в HR.</p><p>Представьте, что два инженера увлеченно спорят об архитектуре: перебивают друг друга, говорят громко, каждый настаивает на своем. Третий коллега идет к руководителю и взволнованно сообщает, что в команде глубокий конфликт. Двое из начала абзаца искренне удивляются: какой конфликт, мы просто разговаривали. Но наблюдатель снаружи видит драку.</p><p>Проблема возникает, когда команда не договорилась, что считать нормой. Один воспринимает прямую полемику как рабочий режим, другой как личную атаку. Они будут решать разные задачи в одном разговоре и никогда не придут к общему решению, пока не поймут, что разговаривают на разных языках.</p><h2>Молчание как последствие конфликтофобии</h2><p>Если порыться в памяти, мы вспомним истории, когда инженер предлагал идею, но получил отказ — причем без объяснений, просто нет. Инженер предлагает снова, и снова получает неаргументированный отказ. В такой ситуации мало кто предложит инициативу в третий раз. Психологи называют это выученной беспомощностью — человек перестает пробовать, потому что система не воспринимает предложения. А объяснять детали система не обучена или не планирует, ведь чем больше информации она даст участникам системы, тем больше поводов для споров может возникнуть.</p><p>Проходит полгода, и руководители удивляются: почему никто не проявляет инициативы, почему все приходится тянуть самому. Получается, что боязнь конфликтов через неспособность доносить аргументы порождает дальнейшие проблемы.</p><p>А люди оптимизируют поведение под реальные условия. Те, кто уходит из команд, где их не слышали, редко называют настоящую причину даже во время exit-интервью — говорят про оффер, зарплату, должность. Такой отток не попадает ни в какой дашборд, и поэтому его не замечают.</p><p>Маленькое трение, умноженное на количество людей и рабочих дней, становится реальной проблемой производительности. Разница в том, что не всегда можно четко измерить, когда человек не доволен. Это не видно на графиках, и поэтому проще игнорировать, но трение точно ощущается человеком изо дня в день.</p><p>Команды, которые застревают в спорах о технологиях, обычно делают это не из-за недостатка экспертизы. Оказывается, что, когда нет безопасного способа не соглашаться и обсуждать разные мнения, никакие условия труда и семинары по управлению конфликтами ситуацию не улучшат. Но чтобы исправить эту проблему, сначала нужно признать, что это вообще проблема — и, главное, проблема не техническая.</p>]]></content:encoded>
    </item>
    <item>
      <title>WebAssembly 3.0 добрался до браузеров: 64-битная память, сборщик мусора и настоящие исключения</title>
      <link>https://tproger.ru/news/webassembly-3-0-dobralsya-do-brauzerov--64-bitnaya-pamyat--sborshhik-musora-i-nastoyashhie-isklyucheniya</link>
      <comments>https://tproger.ru/news/webassembly-3-0-dobralsya-do-brauzerov--64-bitnaya-pamyat--sborshhik-musora-i-nastoyashhie-isklyucheniya?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/webassembly-3-0-dobralsya-do-brauzerov--64-bitnaya-pamyat--sborshhik-musora-i-nastoyashhie-isklyucheniya</guid>
      <description><![CDATA[<p>WebAssembly 3.0 уже работает в браузерах: 64-битная память, полноценный GC, система исключений и новые инструменты для языков</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/webassembly-3-0-dobralsya-do-brauzerov--64-bitnaya-pamyat--sborshhik-musora-i-nastoyashhie-isklyucheniya">WebAssembly 3.0 добрался до браузеров: 64-битная память, сборщик мусора и настоящие исключения</a>»</p>]]></description>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Компиляторы]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Kotlin]]></category>
      <category><![CDATA[Блокчейн]]></category>
      <category><![CDATA[Firefox]]></category>
      <category><![CDATA[WebAssembly]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 18 Sep 2025 03:28:22 GMT</pubDate>
      <content:encoded><![CDATA[<p>Спустя три года после релиза версии 2.0, WebAssembly <a href="https://webassembly.org/news/2025-09-17-wasm-3.0/">получил</a> масштабное обновление.</p><p>Новый стандарт 3.0 уже поддерживается большинством современных браузеров и приносит сразу несколько ключевых нововведений.</p><h2>Главное из нововведений</h2><ul><li><b>64-битная адресация:</b> теперь Wasm может использовать i64 вместо i32, что расширяет лимит адресуемой памяти с 4 ГБ до 16 ЭБ (в реальности — до 16 ГБ в браузерах).</li><li><b>Несколько областей памяти:</b> модули теперь могут напрямую использовать и копировать данные между разной памятью, без обходных трюков с импортом других модулей.</li><li><b>Сборка мусора (GC):</b> добавлена поддержка управляемой памяти для языков с автоматическим управлением памятью (например, Java, Scala, Kotlin, Dart).</li><li><b>Типизированные ссылки:</b> улучшенная типизация ссылок и функций позволяет избежать лишних проверок в рантайме.</li><li><b>Исключения:</b> наконец-то появилась полноценная система обработки исключений — с try, throw и catch, как в других языках.</li><li><b>Хвостовые вызовы:</b> позволяют не занимать стек при возврате через вызов, что критично для функциональных языков и оптимизаций.</li><li><b>Расслабленные SIMD-инструкции:</b> добавлены быстрые, но менее детерминированные версии векторных инструкций для повышения производительности.</li><li><b>Детерминированный профиль:</b> теперь для задач с требованием полной воспроизводимости (например, блокчейны) можно включить строго определенное поведение операций.</li><li><b>Аннотации в тексте:</b> появилась возможность вставлять пользовательские аннотации прямо в текстовый формат .wat.</li></ul><h2>Что это значит</h2><p>WebAssembly становится всё ближе к полноценной виртуальной машине для высокоуровневых языков. В новой версии уже появляются компиляторы для Java, OCaml, Scala и прочих ЯП — благодаря поддержке GC и исключений.</p><p>Новый стандарт уже <b>поддерживается в основных браузерах</b>, включая Chrome и Firefox. Независимые движки, такие как Wasmtime, тоже догоняют.</p>]]></content:encoded>
    </item>
    <item>
      <title>На GitHub выложили исходный код алгоритма рекомендаций X. Разобрались, что там внутри</title>
      <link>https://tproger.ru/news/--na-github-vylozhili-ishodnyj-kod-algoritma-rekomendacij-x--razobralis--chto-tam-vnutri</link>
      <comments>https://tproger.ru/news/--na-github-vylozhili-ishodnyj-kod-algoritma-rekomendacij-x--razobralis--chto-tam-vnutri?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Булат Яббаров]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/--na-github-vylozhili-ishodnyj-kod-algoritma-rekomendacij-x--razobralis--chto-tam-vnutri</guid>
      <description><![CDATA[<p>X выложила на GitHub исходный код алгоритма рекомендаций. Внутри — Scala, Java, Rust и ML-модели для ранжирования твитов, поиска и уведомлений</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/--na-github-vylozhili-ishodnyj-kod-algoritma-rekomendacij-x--razobralis--chto-tam-vnutri">На GitHub выложили исходный код алгоритма рекомендаций X. Разобрались, что там внутри</a>»</p>]]></description>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[Rust]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Сервисы]]></category>
      <category><![CDATA[Twitter]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 10 Sep 2025 08:38:08 GMT</pubDate>
      <content:encoded><![CDATA[<p>Компания X (экс-Twitter) опубликовала исходники алгоритма, отвечающего за рекомендации в ленте «Для вас», поиске и уведомлениях.</p><p>Репозиторий уже <a href="https://github.com/twitter/the-algorithm">собрал</a> почти 65 000 звезд на GitHub. Разбираемся, как он устроен и какие интересные модули лежат внутри.</p><h2>Что делает этот алгоритм</h2><p>Алгоритм отвечает за то, какие посты и аккаунты вы видите на всех основных страницах в X: от рекомендаций и трендов до пушей. Внутри — десятки сервисов и моделей, взаимодействующих между собой.</p><p>Например, компонент home-mixer собирает кандидатные твиты из разных источников (например, через search-index, tweet-mixer, user-tweet-entity-graph) и ранжирует их при помощи легкой и тяжелой нейросети (light-ranker, heavy-ranker).</p><p>После этого подключаются фильтры (например, visibility-filters), которые убирают нежелательный контент и скрытые посты.</p><figure><img src="https://media.tproger.ru/user-uploads/111041/2025-09-10/ccd962a9-c580-4418-990f-737091a615d3.jpeg" alt="" /></figure><h2>Из чего это все собрано</h2><p>Проект построен на Scala (66%), Java (20%) и Rust. Некоторые модули используют Python и даже TensorFlow v1 (например, twml). Базовые компоненты включают:</p><ul><li>Данные — tweepypie, unified-user-actions, user-signal-service</li><li>Модели — SimClusters, TwHIN, real-graph, tweepcred, trust-and-safety-models</li><li>Фреймворки — navi (на Rust), product-mixer, representation-scorer, representation-manager</li></ul><p>Также присутствуют специфические компоненты для пушей — сервис pushservice, ранжирующие модели pushservice-light-ranker и pushservice-heavy-ranker, предсказывающие, откроет ли пользователь уведомление.</p><h2>Почему это важно</h2><p>Во-первых, X остается одной из крупнейших социальных платформ в мире, и понимание ее алгоритмов дает представление о принципах ранжирования и фильтрации контента.</p><p>Во-вторых, открытый код — это редкость в мире коммерческих рекомендаций, особенно на таком масштабе.</p><p>Разработчики предлагают сообществу вносить улучшения через пул-реквесты, участвовать в программах по поиску уязвимостей и разрабатывать на базе кода собственные сервисы.</p><h2>Что это значит для разработчиков</h2><p>Этот проект — хорошее поле для изучения реального промышленного машинного обучения. Особенно интересны:</p><ul><li>плотные графовые эмбеддинги в TwHIN</li><li>модели репутации и социальной близости в real-graph и tweepcred</li><li>многозадачные модели в pushservice-heavy-ranker</li></ul><p>Проект можно собрать с помощью Bazel, хотя полноценной инфраструктуры для тестов пока нет.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как сеньоры документируют проекты: протокол архитектурных решений</title>
      <link>https://tproger.ru/articles/kak-senory-dokumentiruyut-proekty--protokol-arhitekturnyh-rewenij</link>
      <comments>https://tproger.ru/articles/kak-senory-dokumentiruyut-proekty--protokol-arhitekturnyh-rewenij?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Даровская Маша]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-senory-dokumentiruyut-proekty--protokol-arhitekturnyh-rewenij</guid>
      <description><![CDATA[<p>Как сеньоры документируют архитектуру без боли. Обзор подхода ADR: шаблоны, примеры из практики и комментарии экспертов. Ускорьте онбординг и перестаньте объяснять одно и то же.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-senory-dokumentiruyut-proekty--protokol-arhitekturnyh-rewenij">Как сеньоры документируют проекты: протокол архитектурных решений</a>»</p>]]></description>
      <category><![CDATA[API]]></category>
      <category><![CDATA[Git]]></category>
      <category><![CDATA[Unity]]></category>
      <category><![CDATA[Опрос]]></category>
      <category><![CDATA[Практика]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[SQL]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Tor]]></category>
      <category><![CDATA[HTML]]></category>
      <category><![CDATA[GitHub]]></category>
      <category><![CDATA[Боты]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Amazon]]></category>
      <category><![CDATA[HR]]></category>
      <category><![CDATA[GitLab]]></category>
      <category><![CDATA[MIT]]></category>
      <category><![CDATA[Финтех]]></category>
      <category><![CDATA[Фронтенд]]></category>
      <category><![CDATA[Lua]]></category>
      <category><![CDATA[Бэкенд]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[PostgreSQL]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 09 Sep 2025 10:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p><i>Это перевод <a href="https://dev.to/koladev/how-senior-software-engineers-document-their-project-1nf4">статьи</a> автора <a href="https://dev.to/koladev">Мангабо Колаволе</a> с портала DevTo с комментариями экспертов.</i></p><p>Есть одна задача, которую программисты терпеть не могут — но именно она отличает хорошего инженера от посредственного: как они документируют свой проект? Несколько лет назад я отвечал за запуск финтех-проекта. Мы выбрали стратегию быстрого старта, поэтому масштабируемость не стала для нас приоритетом. Главной целью было проверить гипотезу — и мы двигались вперёд, разрабатывая API, архитектуру и системы —  с упором на простоту, не особенно задумываясь о будущем.</p><p>Но я отвечал за бэкенд и инфраструктуру — и понимал: как бы хороша ни была моя память, через шесть месяцев я не смогу вспомнить все технические детали.</p><p>Во время работы я наткнулся на подход, который мне очень понравился: ADR — Architectural Decision Record, или «протокол архитектурных решений».</p><figure><img src="https://media.tproger.ru/user-uploads/102593/2025-09-05/7d1206a7-6729-4bcb-ab55-63d59240df12.png" alt="" /></figure><p>По сути, это документ, в котором
фиксируются все изменения, внесённые в архитектуру: само решение, его влияние и
полученные уроки.</p><p>Проще говоря, это как личный дневник —
только для всей команды.</p><h2>Почему это важно?</h2><p><b>Память
— ненадёжна.</b> Мы часто забываем, почему выбрали одну
архитектурную модель, а не другую. Документирование изменений помогает
восстановить ход мыслей и избежать повторения одних и тех же ошибок.</p><p><b>Это
усиливает команду.</b> Представьте, что вы перепробовали
несколько вариантов решения проблемы и зафиксировали как удачные, так и
неудачные попытки. Это не просто ваш личный опыт — это знание, которым могут
воспользоваться все, включая тех, кто придёт после вас.</p><p><b>Будущие
разработчики скажут вам спасибо.</b> Подумайте о человеке,
который через пять лет будет разбираться в вашем коде. Если вы не оставили
объяснений, он, скорее всего, будет мучиться, пытаясь понять, зачем было
сделано то или иное изменение. А теперь представьте другого разработчика в
другой компании, который находит ADR-документ с чётким объяснением принятого
решения. Он, без сомнения, будет вам благодарен.</p><p>Синьор-фронтендер из ВК Маргарита Лукина, автор телеграм-канала <a href="https://t.me/frontend_kitchen">«Фронтенд кухня»</a>:</p><blockquote>Ценность ADR я впервые осознала в 2019 году. В команду, где работала, активно набирали новых ребят, и приблизительно раз в неделю кто-нибудь из новых разработчиков спрашивал "а почему это сделано так, а не иначе?" Приходилось постоянно давать ответы на одни и те же вопросы, и тогда-то я и поняла, насколько будет удобно записывать ответы где-нибудь в документацию в confluence и просто кидать ссылку новичкам. <br /><br />В 2019 году я еще не знала сам термин ADR и говорила "документация". С термином я познакомилась совсем недавно — этим летом, на курсе по архитектуре монолитных приложений. Тогда я поняла, насколько эффективно можно использовать ADR для ускорения разработки и уменьшения TTM. Дело в том, что начиная разрабатывать новый проект, разработчик первое время (от месяца до полугода! всё зависит от размера проекта) погружается в проект — разбирается, как всё устроено, чтобы вносить изменения соответственно архитектуре. В этот период разработчик, по сути, составляет собственные adr —  обычно в виде мыслеобразов в своей голове :) Если записать основные решения, разработчик сможет намного быстрее погрузиться в проект.</blockquote><h2>Как писать ADR?</h2><p>Существует несколько общепринятых правил, но
вы всегда можете адаптировать их под себя.</p><p>Вдохновившее меня соглашение можно найти на <a href="https://adr.github.io/madr/">GitHub</a>
. Вы также можете ознакомиться с процессом <a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/architectural-decision-records/adr-process.html">ADR на Amazon</a>.</p><p>Вот пример шаблона, который вы можете
использовать.</p><p>Такой тип документа может находиться прямо в репозитории проекта, в Confluence или, например, в JIRA.</p><p>В моей последней компании, где я работал фронтенд-разработчиком, не существовало одного централизованного документа, фиксирующего все архитектурные изменения. Вместо этого мы использовали задачи GitLab и привязывали каждое архитектурное изменение к соответствующей ветке. Это позволяло отслеживать причины изменений даже спустя месяцы после их внедрения.</p><p>Практика спасала нас бесчисленное количество раз. Как я всегда говорю: не важно, насколько вы или ваши коллеги умны — будь то технический директор, менеджер или любой другой участник команды — никто не помнит каждое техническое решение, принятое два года назад.</p><p>Синьор-фронтендер из ВК Маргарита Лукина, автор телеграм-канала <a href="https://t.me/frontend_kitchen">«Фронтенд кухня»</a>:</p><blockquote>Многие руководители хотят видеть на своём проекте разработчиков, которые "сразу, без раскачки" начнут перформить. Совсем избежать периода погружения невозможно, но можно ускорить его в десятки раз за счёт ADR</blockquote>]]></content:encoded>
    </item>
    <item>
      <title>Что такое рекурсия и как с ней работать: разбираемся на примерах</title>
      <link>https://tproger.ru/articles/chto-takoe-rekursiya-i-kak-s-nej-rabotat</link>
      <comments>https://tproger.ru/articles/chto-takoe-rekursiya-i-kak-s-nej-rabotat?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Анна Ельцова]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/chto-takoe-rekursiya-i-kak-s-nej-rabotat</guid>
      <description><![CDATA[<p>Что такое рекурсия - Основы работы с рекурсией - Tproger
description: Что такое рекурсия. Показываем, как правильно работать с рекурсией и когда она нужна. Рассматриваем пошаговую инструкцию и примеры ✔ Tproger
</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/chto-takoe-rekursiya-i-kak-s-nej-rabotat">Что такое рекурсия и как с ней работать: разбираемся на примерах</a>»</p>]]></description>
      <category><![CDATA[Рекурсия и динамика]]></category>
      <category><![CDATA[Языки программирования]]></category>
      <category><![CDATA[Производительность]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Haskell]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Графы]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 05 Mar 2025 14:00:03 GMT</pubDate>
      <content:encoded><![CDATA[<p>Рекурсия — это мощный инструмент в программировании, который позволяет решать задачи, разбивая их на более простые подзадачи. В статье рассмотрим базовые понятия рекурсии, её принципы, примеры использования, а также типичные проблемы, с которыми можно столкнуться при написании кода.</p><h2>Рекурсия: что это такое и зачем нужна</h2><p>Рекурсия — функция, которая вызывает саму себя. Ее базовое применение — разбить большую задачу на несколько мелких, что делает код проще и понятнее, или когда нужно повторить какое-то действие несколько раз. Второй случай похож на русскую матрешку — вы достаете куклу за куклой, пока не дойдете до самой маленькой.</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-02-27/1ac7a0f3-4cad-4616-8226-f5814dbc266e.jpg" alt="" /></figure><p>А теперь давайте разберемся на простом примере из математики: представим, что у нас есть функция F, которая выполняет определенное действие. В нашем случае — вычисляет факториал числа (это самый классический пример). Внутри этой функции F в качестве одного из значений используем вызов этой же функции F, но с уменьшенным аргументом. Так функция будет вызывать саму себя до тех пор, пока не достигнет базового случая (о нем расскажем ниже), после чего начнет возвращать результаты.</p><p>В виде кода это выглядит так:</p><p>Здесь функция F вычисляет факториал числа n, умножая его на факториал n-1, и так до тех пор, пока не дойдёт до 1, после чего начнёт возвращать результаты вверх по цепочке вызовов. Этот пример как раз о том, что нужно выполнить несколько одинаковых действий.</p><p>А вот пример из жизни: вы листаете ленту в известной социальной сети, а новые посты обновляются автоматически — это рекурсия в действии.</p><h2>Принципы работы рекурсии</h2><p>Рекурсия строится на двух ключевых принципах: базовый случай и рекурсивный вызов. Они позволяют функции вызывать саму себя, пока она не завершится.</p><h3>Базовый случай</h3><p>Базовый случай рекурсии — условие, при котором рекурсивный вызов прекращается. Без него функция будет вызывать саму себя бесконечно, а значит, стек переполнится.</p><p>Один из самых простых примеров — факториал, о котором мы писали выше. Другой — возведение числа в степень до тех пор, пока значение не станет равно искомому.</p><p>Так это выглядит в виде кода:</p><p>То есть, базовый случай — если exponent == 0, то возвращаем 1.</p><h3>Рекурсивный вызов</h3><p>Рекурсивный вызов — шаг, на котором функция вызывает саму себя, но с измененными параметрами, чтобы задача стала проще. Один из еще одних классических примеров — задача с числами Фибоначчи.</p><p>Числа Фибоначчи — это последовательность, где каждое число равно сумме двух предыдущих: 0, 1, 1, 2, 3, 5, 8, 13, 21, …</p><p>Если вызвать fibonacci(5), то увидите следующее:</p><p>После этого функция возвращает результаты обратно вверх по стеку вызовов. Обычно этот метод используется в криптографии и алгосах.</p><p>Кстати, на примере чисел Фибоначчи можно разобрать одну из проблем рекурсии — плохая производительность при отсутствии мемоизации.</p><p>Мемоизация — техника оптимизации, при которой результаты больших вычислений сохраняются и используются еще раз при повторных вызовах функции. Это особенно полезно, если работаете с рекурсиями, которые могут вычислять одни и те же значения много раз.</p><p>Так, функция  в задаче с числами Фибоначчи имеет экспоненциальную сложность O(2^n), так как она многократно вычисляет одни и те же значения. Например, чтобы вычислить fibonacci(5), функция вызывает сама себя 15 раз, хотя уникальных вычислений всего 6.</p><p>Чтобы улучшить производительность, нужно использовать мемоизацию, чтобы сохранить результаты:</p><p>Здесь сложность уменьшается до O(n), так как каждое значение вычисляется только один раз.</p><h2>Стек вызовов и управление памятью</h2><p>Каждый рекурсивный вызов функции добавляет новый элемент в стек вызовов. Это значит, что вызовы складывается в стеке до тех пор, пока не будет достигнут базовый случай. После этого стек начинает разворачиваться, возвращая результаты на каждом уровне.</p><p>Например:</p><p>Так, когда мы вызываем сountdows(3), в стеке появляются новые вызовы:</p><p>call countdown(3)  # → печатает 3</p><p>call countdown(2)  # → печатает 2</p><p>call countdown(1)  # → печатает 1</p><p>call countdown(0)  # → печатает "Старт" и выходит</p><p>Затем стек начинает разворачиваться:</p><ul><li>countdown(0) завершился → удаляется из стека</li><li>countdown(1) завершился → удаляется из стека</li><li>countdown(2) завершился → удаляется из стека</li><li>countdown(3) завершился → удаляется из стека</li></ul><p>Если же в рекурсии нет базового случая, то стек вызовов никогда не освободится, и программа (в нашем случае на Питоне) выдаст ошибку RecursionError.</p><p>Вот пример бесконечной рекурсии:</p><p>В Питоне есть ограничения до 1000 вызовов, чтобы не перегружать стек, но этот лимит можно увеличить:</p><h2>Рекурсия на реальных задачах</h2><p>С базовым случаем и рекурсивным вызовом все понятно, поэтому давайте разбираться на более реальных и сложных примерах — с деревьями, графами и массивами.</p><h3>Обход структуры данных</h3><p>Рекурсия часто используется для обхода деревьев и графов. Например, бинарного дерева — в нем не более двух дочерних узлов (левый и правый). Вот три основных способа обхода:</p><ol><li>Прямой обход (Pre-order): Корень → Левый узел → Правый узел.</li><li>Симметричный обход (In-order): Левый узел → Корень → Правый узел.</li><li>Обратный обход (Post-order): Левый узел → Правый узел → Корень.</li></ol><p>Запишем в виде кода:</p><p>Дерево будет выглядеть так:</p><p>1</p><p>/ \</p><p>2   3</p><p>/ \</p><p>4   5</p><ul><li>Прямой обход: 1 → 2 → 4 → 5 → 3.</li><li>Симметричный обход: 4 → 2 → 5 → 1 → 3.</li><li>Обратный обход: 4 → 5 → 2 → 3 → 1.</li></ul><p>Обходить можно и графы, особенно в глубине (DFS). Вот пример:</p><p>Сам граф:</p><p>Результат обхода: A → B → D → E → F → C.</p><h3>Разбиение</h3><p>Разбить можно массив или строку. Давайте разбираться на примере строки. Так, рекурсия может разбить строку на слова или разделить ее по конкретным символам. Выглядит это так:</p><h2>Что такое хвостовая рекурсия</h2><p>Хвостовая (оконечная) рекурсия — частный случай рекурсии. Главное отличие от обычной в том, что единственный рекурсивный вызов находится в конце перед выходом функции. В традиционной же рекурсии после рекурсивного вызова могут быть дополнительные вычисления.</p><p>Вот пример:</p><p>Кстати, с помощью хвостовой рекурсии тоже можно решать задачи с числами Фибоначчи:</p><p>Некоторые языки программирования (например, Haskell и Scala) поддерживают оптимизацию хвостовой рекурсии. Это означает, что компилятор или интерпретатор преобразует хвостовую рекурсию в итерацию — это помогает избежать переполнение стека.</p><p>Давайте посмотрим, как это работает в Scala. Вот обычная рекурсия, чтобы понять принцип:</p><p>А вот рекурсия с оптимизацией:</p><p>К сожалению, наш любимый Питон такую функцию не поддерживает, но всегда можно преобразовать «хвостика» в итерацию вручную:</p><p>Это пример итеративного решения факториала.</p><h2>Рекурсия vs. итерация</h2><p>Основные различия между рекурсией и итерацией заключаются в следующем:</p><ul><li>В рекурсии функция вызывает саму себя, а в итерации используются циклы.</li><li>Интеграция требует меньше памяти, потому что нет стека вызовов.</li><li>Рекурсия медленнее без оптимизации.</li><li>С рекурсией легко переполнить хранилище при большой глубине.</li><li>Рекурсия обычно более читаемая и лаконичная, но подходит для меньшего количества задач.</li></ul><p>Итерацию лучше использовать в следующих случаях:</p><ul><li>Задачи, где нужна производительность. Как, например, с итеративным вычислением чисел Фибоначчи.</li><li>Обработка больших данных, например, поиск или сортировка. Вот пример пузырьковой сортировки:</li></ul><ul><li>Задачи с большой глубиной рекурсии, чтобы стек не переполнялся. Вот как итеративно обойти дерево:</li></ul><h2>Еще один пример: задача «Ханойские башни»</h2><p>«Ханойские башни» — классная головоломка, которую часто решают с помощью рекурсии. Считайте, что это еще одна классика.</p><p>Есть три стержня: A, B и C. На стержень A нанизано несколько дисков разного размера, причем диски упорядочены по размеру в виде пирамидки — вниз от маленького к большому. Суть в том, чтобы переместить все диски со стержня А на С, при этом: за один раз можно перемещать только один диск, нельзя класть больший диск на меньший, можно использовать стержень B как вспомогательный.</p><figure><img src="https://media.tproger.ru/user-uploads/101078/2025-02-27/c2ccaa24-e4b7-4d2f-8ae8-ac894801834a.png" alt="" /></figure><p>Рекурсивное решение задачи «Ханойские башни» основано на следующей идее:</p><ol><li>Переместить (n−1) дисков с A на B, используя C как промежуточный.</li><li>Переместить оставшийся самый большой диск с A на C.</li><li>Переместить (n−1) дисков с B) на C, теперь используя A как промежуточный.</li></ol><p>Следовательно, если количество дисков n=1, просто переместите его с А на С (базовый случай). В остальных случаях при n–1 повторить то, что указано выше.</p><p>А теперь решение с помощью кода:</p><p>Вывод:</p><p>Поздравляем, вы великолепны. А если хотите еще потренироваться в рекурсии, то можно написать код для поиска пути в лабиринте (кстати, это чем-то напоминает онлайн-карты и навигаторы) или обратного вывода строки.</p>]]></content:encoded>
    </item>
    <item>
      <title>«Какой функциональный язык программирования стоит выбрать начинающему разработчику?» — советы от пользователей Reddit</title>
      <link>https://tproger.ru/articles/-kakoj-funkcionalnyj-yazyk-programmirovaniya-stoit-vybrat-nachinayushhemu-razrabotchiku-----sovety-ot-polzovatelej-reddit</link>
      <comments>https://tproger.ru/articles/-kakoj-funkcionalnyj-yazyk-programmirovaniya-stoit-vybrat-nachinayushhemu-razrabotchiku-----sovety-ot-polzovatelej-reddit?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Мария Кривоченко]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/-kakoj-funkcionalnyj-yazyk-programmirovaniya-stoit-vybrat-nachinayushhemu-razrabotchiku-----sovety-ot-polzovatelej-reddit</guid>
      <description><![CDATA[<p>Начинающий разработчик решил изучать функциональное программирование и не уверен, какой язык ему выбрать. Рассказываем, что ему посоветовали.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/-kakoj-funkcionalnyj-yazyk-programmirovaniya-stoit-vybrat-nachinayushhemu-razrabotchiku-----sovety-ot-polzovatelej-reddit">«Какой функциональный язык программирования стоит выбрать начинающему разработчику?» — советы от пользователей Reddit</a>»</p>]]></description>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Функциональное программирование]]></category>
      <category><![CDATA[Работа]]></category>
      <category><![CDATA[Советы]]></category>
      <category><![CDATA[TypeScript]]></category>
      <category><![CDATA[Haskell]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Lisp]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 23 Jan 2024 16:40:16 GMT</pubDate>
      <content:encoded><![CDATA[<p>Недавно пользователь под ником HistoricalAccess9501 рассказал, что интересуется функциональным программированием, но не знает, с какого языка ему начать:</p><p>Множество людей советовали мне изучить Haskell, Scala, Clojure, Erlang или Lisp, потому что они помогут хорошо понять функциональное программирование. Но я не уверен, за какой стоит взяться в первую очередь. У меня есть опыт работы с Python и JS, но я ни разу не сталкивался с функциональными языками программирования, поэтому также хочется знать, какие языки для чего используются: приложения, сайты, игры, машинное обучение и так далее.</p><p>В ответ HistoricalAccess9501 получил несколько дельных советов.</p><p><b>UdPropheticCatgirl</b></p><p>Я думаю, что любой из потомков и диалектов Lisp подойдет, например, SBCL или Clojure (и, возможно, Racket).</p><p>Можно взяться за Elixir, Erlang и Gleam, особенно чтобы разобраться в BEAM. Если вы хорошо знакомы с акторами и IPC. Scala великолепен, но многим отличается от большинства функциональных языков, поэтому не стоит учить его в первую очередь. Еще я бы не брался за Haskell и вместо него учил OCaml.</p><p>Что касается сфер применения:</p><ul><li>Scala используется для построения дата-пайплайнов, и для бэкенда на Java.</li><li>Clojure — оптимальный Lisp, для работы в 2024, в основном если пишете бэкенд на Java.</li><li>SBCL сегодня встречается редко, я сталкивался с ним только во время работы с HFT, еще в какой-то момент его часто использовали в сфере ИИ, но не уверен, продолжают ли сейчас.</li><li>Elixir — снова бэкенд, особенно если работаете с распределенными системами.</li><li>Erlang — король распределенных систем, часто используется в телекоме.</li><li>Haskell подходит, только если вам не о чем поговорить с курьером и перед партией в D&amp;D.</li><li>OCaml используется примерно в двух финтех-компаниях и некоторыми небольшими анализаторами в Meta, вот и все.</li></ul><p><b>VicariousAthlete</b></p><p>F# просто замечательный — мой лучший опыт в этой сфере. Сейчас мы используем его в создании масштабных систем (заказ еды онлайн).</p><p><b>nandryshak</b></p><p>Сначала определите, какие концепции вы хотите изучить, а потом подберите под нее язык. Не забудьте про популярность языка — хорошее сообщество и большой набор инструментов упростят обучение.</p><ul><li>Функции первого класса, составные функции и прочее? — Javascript, Racket.</li><li>Все вышеперечисленное плюс неизменяемые объекты? — Clojure.</li><li>Все вышеперечисленное плюс хорошая система типов? Typescript.</li><li>Все вышеперечисленное плюс, Хиндли-Милнер и математика? — Haskell.</li></ul><p>&lt;…&gt;</p><p><b>Joewoof</b></p><p>Сложно выбрать. Самый простой и популярный — Scala, но это мультипарадигмальный язык. Haskell слишком редкий. Что-то среднее?</p><p>Наверное, OCaml. Он преподается как первый в Кембридже, у него хорошая репутация. Если хотите что-то более практичное, то выбирайте Elixir.</p><p><b>0xAERG</b></p><p>Если вы знакомы с JS и хотите что-то похожее, советую попробовать изучить ReScript. Он функциональный, компилируется в JavaScript, а синтаксис похож на смесь OCalm и JS. &lt;…&gt;</p><p><b>davadds0</b></p><p>В университете я изучал Erlang и Scheme.</p><p>Рекомендую сначала изучить Erlang (сначала хорошо освоить vanilla Erlang), а затем — OTP, что-то вроде библиотеки/фреймворка Erlang, это спасет вас от монотонной работы. А еще будет удобно создавать сложные распределенные системы с помощью Erlang/OTP. &lt;…&gt;</p><p><b>Peiple</b></p><p>Из необычного — R, который полезен на практике. Он не такой хардкорный, как Haskell, но содержит большинство концепций функционального программирования. В основном используется в Data Science. &lt;…&gt;</p><p><b>Frenchslumbe</b></p><p>Самый легкий в освоении — Lips.</p><p>Простой и последовательный синтаксис (но при этом очень выразительный). К тому же, изучив Lips, будет проще с его диалектами и языками-потомками. &lt;…&gt;</p><p>Также советую ClojureScript. Это реализация Clojure, с компиляцией в JavaScript.</p><p>А что бы вы посоветовали, начинающим изучать функциональное программирование?</p>]]></content:encoded>
    </item>
    <item>
      <title>Как перейти с Java на Scala</title>
      <link>https://tproger.ru/articles/kak-perejti-s-java-na-scala</link>
      <comments>https://tproger.ru/articles/kak-perejti-s-java-na-scala?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Рафаил Агазода]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/kak-perejti-s-java-na-scala</guid>
      <description><![CDATA[<p>Вместе с разработчиками компании «Криптонит» составили дорожную карту по изучению Scala для Java-разработчиков.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/kak-perejti-s-java-na-scala">Как перейти с Java на Scala</a>»</p>]]></description>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Партнёрский материал]]></category>
      <category><![CDATA[Планы обучения]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 28 Mar 2023 07:00:34 GMT</pubDate>
      <content:encoded><![CDATA[<p>Scala — редкий, местами сложный в освоении и вместе с тем высокооплачиваемый язык программирования. Он полностью совместим с Java и работает на той же виртуальной машине. Поэтому, имея опыт разработки на Java, стать «скалистом» будет проще.</p><p>Вместе с разработчиками технологической и научно-исследовательской компании «Криптонит» мы составили дорожную карту по изучению Scala. Этот роадмап подойдёт Java-разработчикам, которые хотят освоить больше связанных технологий.</p><ol><li><a href="https://tproger.ru/#part1">Зачем переходить на Scala</a></li><li><a href="https://tproger.ru/#part2">Задачи и возможности Scala</a></li><li><a href="https://tproger.ru/#part3">Чем занимается Scala-программист</a></li><li><a href="https://tproger.ru/#part5">Общие инструменты</a></li><li><a href="https://tproger.ru/#part9">Полезные материалы для изучения Scala</a></li></ol><h2>Зачем переходить на Scala</h2><p>Чтобы начать осваивать новый язык, должны быть веские причины. Особенно для Java-разработчиков, которые пишут на одном из самых востребованных языков программирования.</p><p>Scala создавался как преемник Java. Он унаследовал лучшее от предшественника и стал технически совершеннее. Scala более объектно-ориентирован, чем Java, а также обладает возможностями функционального языка. Сочетание двух подходов делает программирование на Scala гибким, повышает эффективность кода и позволяет реализовывать нестандартные решения.</p><p>В Scala есть сильные механизмы абстракции, которые позволяют легко программировать как большие, так и маленькие системы и масштабировать их. А ещё код на Scala компактнее по сравнению с Java. Выразительный синтаксис позволяет избегать багов, ускоряет написание и упрощает чтение программ.</p><p>Несмотря на свои сильные стороны, Scala не получил такого же распространения, как Java. Однако относительная нишевость языка — на руку программистам. Она компенсируется высоким уровнем средних зарплат и возможностью работать над уникальными проектами.</p><h2>Задачи и возможности Scala</h2><p>Scala — многофункциональный язык программирования, который применяется для решения различных задач. Сегодня возможности Scala используют для разработки распределённых систем, научных вычислений, мобильных и веб-приложений и приложений для анализа данных.</p><p>Писать на Scala сложнее, чем на Java. Язык требует совершенно другого подхода к архитектуре и логике построения кода. Но вместе с этим Scala имеет ряд преимуществ:</p><p>— Функциональное программирование. Scala обладает функциональными возможностями, что идеально подходит для решения сложных задач, связанных с обработкой данных и параллельным программированием.</p><p><b>— </b>Безопасность типов. Scala имеет более строгую систему типов, чем Java, что позволяет предотвращать ошибки на этапе компиляции, а не на этапе выполнения.</p><p><b>— </b>Интероперабельность с Java. Язык полностью совместим с Java, поэтому Scala-разработчики могут использовать библиотеки Java и легко взаимодействовать с Java-кодом.</p><p>— Поддержка асинхронного программирования. Различные инструменты в Scala делают язык идеальным для создания высокопроизводительных приложений.</p><p><b> — </b>Конкурентность. Scala предлагает мощную поддержку параллелизма и конкурентности, которые важны для написания высокопроизводительных приложений и сервисов. Scala-код может быть выполнен на JVM, что позволяет использовать все преимущества JVM, включая возможности управления памятью и оптимизации.</p><p><b>— </b>Масштабируемость. Scala позволяет разработчикам создавать масштабируемые приложения, которые могут обрабатывать большие объемы данных и выдерживать высокие нагрузки.</p><p>А ещё Scala — один из самых динамично развивающихся языков и постоянно внедряет новые возможности. Сейчас активно развивается следующая итерация языка — Scala 3. В ней переработали компилятор, что улучшило автоматический вывод типов и снизило многословность кода. Одновременно с этим вышел из экспериментального статуса механизм макросов, который расширил возможности автоматической генерации кода.</p><h2>Чем занимается Scala-программист</h2><p>Согласно <a href="https://survey.stackoverflow.co/2022">исследованию</a> Stack Overflow, доля Scala-разработчиков среди профессиональных программистов — около 3%. И компании активно ищут таких специалистов: в марте 2023 года только на карьерной площадке Linkedin размещено почти 34 тысячи соответствующих вакансий.</p><p>Одним из направлений, требующих знания Scala, является backend-разработка. На этой позиции от кандидатов требуют умение писать код на Scala, наличие аналитического склада мышления, умение разбираться в доменной области и логике работы системы.</p><p>Бэкендеры занимаются разработкой сервисов, связанных с бизнес-логикой системы. Например, в «Криптоните» ищут <a href="https://tprg.ru/NLZC">Scala-разработчиков</a>, которые возьмутся за реализацию серверной части веб-приложений, связанных с обработкой и отображением больших данных, а также <a href="https://tprg.ru/BeoU">начинающих «скалистов»</a>, которые будут разрабатывать отдельные компоненты приложений и проводить их автоматическое тестирование.</p><p>До того, как стал писать на Scala коммерческие проекты, я уже знал Java, JavaScript и C. Примерно в 2012 году стали много говорить о том, что Java скоро умрёт и будут новые языки. Scala назывался как один из них, и я решил попробовать. Оказалось, это интереснее, чем писать на Java. Однако у «скалистов» более высокий порог входа. Чтобы начать писать на этом языке, нужно чуть больше знаний, чем для программирования на Java. На Scala я пишу почти 10 лет. Сначала делал небольшие программы для себя. Они выполняли какие-то рутинные действия, помогая мне в основной работе. Например, я сделал редактор protobuf’а (формата сериализации структурированных данных Protocol Buffers, который по сравнению с XML обеспечивает более компактное хранение и повышает скорость обработки данных). Особенно понравилось, что в среде разработки Scala есть консоль (среда программирования REPL с интерфейсом командной строки). В ней можно писать код в интерактивном режиме и тут же его выполнять. В «Криптоните» я занимаюсь бэкендом для клиента интеллектуальной системы транскрибации голоса. Это очень перспективная тема, и её интересно реализовать на Scala. Ещё я сейчас работаю над сервисами для платформы обработки больших данных. Я выполнил оптимизацию кода и потребления вычислительных ресурсов, используя принцип разделения функционала. Получились отдельные лёгкие микросервисы.</p><p>Кроме backend-разработки, у Scala-программистов есть карьерные перспективы в обработке данных. Это направление требует широкого кругозора и понимания того, по каким принципам строятся распределённые системы. Также для работы понадобятся сильные технические навыки, знание тонкостей работы платформы JVM и облачной инфраструктуры.</p><p>Впервые о языке Scala я узнал в 2015 году. Я уже знал Java, а также успел поучаствовать на проектах с Python, Ruby и немного — с JavaScript. Мой первый проект на Scala был связан с обработкой результатов тестов в генетической лаборатории. Он состоял из двух отдельных частей: ETL (извлечение, преобразование и загрузка) огромного потока данных и backend для отображения статистики. В «Криптоните» я занимаюсь разработкой ПО для наших заказчиков: поиском и обработкой больших массивов данных, транскрибацией голосовых сообщений, а также участвую в разработке внутренних проектов — например, сервисом доступа и хранения данных.</p><p>Ещё одно направление для развития — анализ данных. На этой позиции от кандидатов требуют знание Scala, Python, SQL, умение декомпозировать сложные структуры данных на отдельные компоненты, выстраивать гипотезы на основе этих компонент и проводить математические исследования с целью доказательства или опровержения выработанных гипотез.</p><p>Scala-программисты описывают алгоритмы приведения неструктурированных данных к структурированным, находят зависимости и противоречия. Например, в «Криптоните» разрабатывают аналитические системы на базе единой платформы, которые позволяют безопасно работать с данными независимо от их формата, метода хранения и эксплуатации. Сейчас компания ищет <a href="https://tprg.ru/s3pK">тимлида</a> на этот проект.</p><p>По образованию я физик. В университете для научной работы использовал Си и MatLab. Затем на работе нужно было использовать OpenText (OScript) и писать на JavaScript, а для хобби-проектов использовал Java. Программировать на Scala предложили на собеседовании, так как вся команда писала на этом языке. Моей первой задачей, реализованной на Scala, было написание коннектора к чат-серверу. В нём использовался публичный API социальной сети «Одноклассники», чтобы передавать сообщения к чат-серверу и обратно. Требования были такими: максимально быстрая передача сообщений, возможность для масштабирования и отказоустойчивость. В итоге коннектор был реализован мной с использованием набора библиотек Akka для разработки распределённых приложений и параллельных вычислений. В «Криптоните» я занимаюсь конструктором запросов для анализа большого количества данных. У нас в компании все продукты разрабатываются в рамках единой экосистемы, поэтому необходим сервис, который может их связывать. Конечная цель этого сервиса — возможность выстраивать компоненты для анализа различного типа данных (текст, изображение, аудио) в единую цепочку для их обработки. Коллеги из лаборатории больших данных и статистики приносят нам готовые ML-модели, а мы пишем на Scala сервис для конструктора запросов, который склеивает всё это в единый продукт.</p><h2>Общие инструменты</h2><p>Напомним, что Scala-разработчику доступны все JVM-библиотеки, написанные на Java, Kotlin и других. Поэтому в статье разберём только те инструменты, которые написаны на Scala или имеющие соответствующий API.</p><h3>Основы языка</h3><p>Изучение Scala с нуля стоит начать со стандартной библиотеки языка. Она сочетает в себе изменяемые и неизменяемые структуры данных, а предоставляемые ей интерфейсы используются во всех сторонних библиотеках.</p><p>Кроме этого, на начальном этапе освоения Scala необходимо подробно изучить понятия рекурсии и лямбда-функций, которые с каждым годом начинают всё больше использоваться и в ООП-языках.</p><h3>Компиляция проектов</h3><p>Несмотря на возможность сборки Scala-проектов с помощью gradle и maven, рекомендуем освоить работу <a href="https://www.scala-sbt.org/">Scala Build Tool</a>. С помощью этого инструмента можно настраивать параметры компиляции проектов: выставлять необходимые флаги компилятора языка, разбивать проект на подмодули, осуществлять кросс-компиляцию с разными версиями библиотек и даже самого языка Scala.</p><h3>Плагины компилятора</h3><p>Scala позволяет не только гибко изменять и комбинировать программы, но и модифицировать этап компиляции проектов при помощи API для создания плагинов.</p><p>Предназначение плагинов компилятора может быть крайне разным. Например, плагины WartRemover и Scapegoat предоставляют инструменты для статического анализа кода, better-tostring изменяет поведение генерируемых по умолчанию функций, а Scala.js и Scala Native позволяют компилировать Scala-код для платформ, отличных от JVM.</p><h3>Работа с консолью</h3><p>Взаимодействовать со Scala-проектами можно не только путём их компиляции и последующего запуска, но и в интерактивном режиме при помощи Scala REPL. Эта консольная оболочка позволяет выполнять команды пользователя построчно. Использовать Scala REPL можно и на основе полноценных компилируемых проектов, и для интерпретации отдельных файлов.</p><p>Для работы с консолью также подходит Ammonite REPL. Это сторонний инструмент с бо́льшим числом возможностей по сравнению с оболочкой по умолчанию. Среди них — подсветка синтаксиса и динамическое подключение зависимостей.</p><h3>Сериализация данных</h3><p>Библиотеки для сериализации и десериализации данных применяются при синхронном взаимодействии сервисов с помощью API, при асинхронном взаимодействии с использованием очередей сообщений и при записи в файл или хранилище данных.</p><p>Хотя самый популярный формат сообщений для межсервисного взаимодействия — JSON, также активно используются Parquet, protobuf, Avro и CSV. Собрали наиболее крупные библиотеки для работы с этими форматами на Scala:</p><ul><li><a href="https://github.com/sksamuel/avro4s">avro4s</a> — библиотека для взаимодействия с форматом Avro;</li><li><a href="https://scalapb.github.io/">ScalaPB</a> — библиотека для генерации protobuf-сообщений;</li><li><a href="https://mjakubowski84.github.io/parquet4s/">parquet4s</a> — библиотека для работы с форматом Parquet;</li><li><a href="https://circe.github.io/circe/">circe</a> — одна из самых популярных библиотек для работы с JSON в функциональном стиле;</li><li><a href="https://github.com/com-lihaoyi/upickle">uJson</a> — минималистичная библиотека для работы с JSON;</li><li><a href="https://github.com/json4s/json4s">json4s</a> — корневая библиотека, предоставляющая интерфейсы для работы с различными JSON-парсерами и сериализаторами.</li></ul><h3>Тестирование</h3><p>Библиотеки для тестирования фокусируются на читаемости тестов и имеют синтаксис, близкий к обычному английскому языку.</p><p>Пример теста, написанного при помощи scalatest:</p><p>Основные фреймворки и библиотеки для тестирования:</p><ul><li><a href="https://www.scalatest.org/">scalatest</a> — фреймворк для тестирования кода, позволяющий гибко выбирать синтаксис написания тестов;</li><li><a href="https://etorreborre.github.io/specs2/">specs2</a> — альтернатива scalatest с фокусом на behavior-driven тестах;</li><li><a href="https://scalacheck.org/">scalacheck</a> — обособленная библиотека тестирования кода путём случайной генерации входных данных. Имеет интеграции с основными фреймворками для тестирования;</li><li><a href="https://scalameta.org/munit/">munit</a> — библиотека для тестирования с акцентом на читаемости ошибок в тестах;</li><li><a href="https://github.com/com-lihaoyi/utest">uTest</a> — минималистичная библиотека для тестирования.</li><li><a href="https://disneystreaming.github.io/weaver-test/">weaver test</a> — библиотека для тестирования с использованием cats-effect.</li></ul><h3>Логирование и конфигурация</h3><p>Конфигурация проектов в Scala зачастую осуществляется на основе файла application.conf, аналогично языку Java. Наиболее популярный формат конфигурации — HOCON. Он позволяет использовать переменные окружения и ссылки на другие элементы конфигурации при её описании. Для чтения конфигурации используют эти библиотеки:</p><ul><li><a href="https://github.com/lightbend/config">lightbend/config</a> — библиотека без сторонних зависимостей, реализованная на языке Java;</li><li><a href="https://pureconfig.github.io/">pureconfig</a> — Scala-библиотека с возможностью автоматической конвертации конфигурации в классы приложения.</li></ul><p>Библиотеки для логирования в основном базируются на Java-интерфейсах. Выбирать библиотеку стоит исходя из совместимости с фреймворком и уменьшения числа зависимостей, используемых в проекте. Основные библиотеки:</p><ul><li><a href="https://github.com/lightbend-labs/scala-logging">scala-logging</a> — высокопроизводительная библиотека-обёртка над slf4j интерфейсами;</li><li><a href="https://github.com/typelevel/log4cats">log4cats</a> — библиотека для логирования в функциональном стиле с интеграцией с cats-effec;</li><li><a href="https://izumi.7mind.io/logstage/index.html">LogStage</a> — оптимизированная библиотека для структурного логирования.</li></ul><h2>Полезные материалы для изучения Scala</h2><p>Чтобы обучение языку Scala было максимально эффективным, следует запастись полезными ресурсами.</p><p><b>Списки Scala-библиотек:</b></p><ul><li><a href="https://index.scala-lang.org/">Scaladex</a></li><li><a href="https://github.com/lauris/awesome-scala">Awesome Scala libraries</a></li></ul><p><b>Telegram-каналы:</b></p><ul><li><a href="https://t.me/scala_ru">Scala User Group</a> — крупнейший русскоязычный чат для обсуждения языка Scala.</li><li><a href="https://t.me/scala_learn">Scala Learning &amp; Education: Ask for Review &amp; Noob questions</a> — чат для начинающих изучать Scala.</li><li><a href="https://t.me/scala_channel_ru">Scala Nishtyaki Channel</a> — канал от создателей сообщества Scala_ru с публикациями статей, докладов и новостей из мира функционального программирования и Scala.</li></ul><p><b>Книги:</b></p><p><b>Курсы и упражнения:</b></p><ul><li><a href="https://www.coursera.org/specializations/scala">Специализация Functional Programming in Scala</a></li><li><a href="https://exercism.org/tracks/scala">Scala on Exercism</a></li><li><a href="https://www.coursera.org/learn/effective-scala">Effective Programming in Scala</a></li><li>Онлайн-книги с упражнениями от <a href="https://underscore.io/books/">Underscore</a></li></ul><h2>Работа для Scala-программистов</h2><p>Если вы готовы перейти с Java на Scala, держите подборку вакансий в «Криптоните». Компания занимается разработкой платформы частного облака с ML-технологиями для аналитики и бизнес-решений. Основной стек технологий компании: Scala, Typescript, Rust, Python, K8S, Spark, Kafka, ClickHouse, Scylla, Postgres, Vue.</p><p>Прямо сейчас «Криптонит» ищет:</p><ul><li><a href="https://tprg.ru/NLZC">Developer</a></li><li><a href="https://tprg.ru/s3pK">Team Lead</a></li><li><a href="https://tprg.ru/BeoU">Стажёр-разработчик (Серверная разработка)</a></li><li><a href="https://tprg.ru/Ml1b">Стажёр-разработчик (Data Engineering)</a></li></ul><p>Переходите по ссылке и станьте частью команды!</p><p><i>Реклама АО «Научно-производственная компания «Криптонит» LjN8KWavY</i></p>]]></content:encoded>
    </item>
    <item>
      <title>Логистический стартап в 2023: что делать, чтобы не пожалеть</title>
      <link>https://tproger.ru/articles/logisticheskij-startap-v-2023-chto-delat-chtoby-ne-pozhalet</link>
      <comments>https://tproger.ru/articles/logisticheskij-startap-v-2023-chto-delat-chtoby-ne-pozhalet?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Kseniya Baburina]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/logisticheskij-startap-v-2023-chto-delat-chtoby-ne-pozhalet</guid>
      <description><![CDATA[<p>Как запустить логистический стартап на примере pet-проекта: какие технологии использовать, как настроить маршрутизацию и выстроить процессы.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/logisticheskij-startap-v-2023-chto-delat-chtoby-ne-pozhalet">Логистический стартап в 2023: что делать, чтобы не пожалеть</a>»</p>]]></description>
      <category><![CDATA[TypeScript]]></category>
      <category><![CDATA[Node.js]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Pet-проекты]]></category>
      <category><![CDATA[Стартапы]]></category>
      <category><![CDATA[Гостевая публикация]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 26 Dec 2022 08:00:04 GMT</pubDate>
      <content:encoded><![CDATA[<p>Логистика за последние 5 лет растет быстрыми темпами и на этом останавливаться не собирается. Это как раз та категория, которая сильно модернизировалась во времена пандемии, когда доставка до дома стала жизненно необходимой историей.</p><p>Давайте рассмотрим, какой же рынок грузоперевозок сейчас в России. Официальные источники утверждают, что объем рынка в 2019 году достиг 900 млрд руб., они, конечно же не учитывают объем «серого» рынка, когда оплата происходит наличными. Хотя, введение самозанятости у водителей сильно обеляет рынок, но оплата «переводом на карту водителю» остается существенной и достигает 30%-40% от всего рынка.</p><p>Запуская свой стартап, мы ориентировались на рынок last mile, который, считается, что занимает до 70% от рынка грузоперевозок. Как принято говорить, это большой красный океан, в котором хотелось найти голубой ручеек.</p><h2>Особенности запуска проекта</h2><p>Для начала пришлось разобраться, как работает логистика на стороне клиента. Оговорюсь сразу, мы пошли в сегмент b2b и не хотели заниматься квартирными переездами, где пришлось бы конкурировать с небезызвестными крупными игроками, которые имеют огромные бюджеты на продвижение.</p><p>Итак, как же работали логисты в крупных и не очень компаниях. Мы назвали это «метод коленки», когда каждый вечер, в 18-00 садятся два менеджера-логиста и начинают раскидывать адреса доставки в excel так, чтобы успеть развести всем клиентам. Это упражнение они делают исходя из своего опыта, ни о каких технологиях и речи нет. Уверена, часть компаний так и остались в этой мезозойской эре.</p><p>На то есть причины: невозможно внедрять что-то новое в логистике, когда у тебя складская программа/бухгалтерия/crm написаны 10 лет назад группой программистов на аутсорсе, которых уже нет. И никто уже не знает, как работает их API, а программист на саппорте уныло разводит руками.</p><p>Для нас такой процесс оказался вызовом, и мы предложили маршрутизацию.</p><h2>Выбор солвера для маршрутизации</h2><p>Сейчас на рынке существует множество универсальных опенсорсных солверов Google OR-Tools, Choco-solver. В каждом есть функционал, который можно настроить для применения различных бизнес правил: вместимость авто, время подачи/загрузки, в нашем случае, даже была задача от клиента, что точку в Кремле можно было давать только одному водителю, т.к он уже прошел миллион проверок и по понятным причинам менять каждый день водителя никто не хотел. Ограничения от клиентов могут быть абсолютно не типовые.</p><p>Итак, свой выбор мы остановили на Google OR-tools, хотя был большой интерес еще к платному Gurobi, но на этапе стартапа сначала ты экономишь и тестируешь. Нам не хотелось лезть в промышленные солверы за большие деньги, тк был план разобраться сначала с тем, что дают бесплатно.</p><p>Чтобы «приготовить» OR-tools так, как нужно, пришлось разбить первоначальную задачу на подзадачи, чтобы соответствовать опциям и ограничениям от заказчиков. Процесс был не супер быстрый, солвер частенько тупил и выдавал «решение не найдено».  Как мы с этим справлялись?</p><p>Идея такая, что сначала мы получаем первое решение, а затем итеративно гоняем на ней модель, иногда возвращая на место ограничения, которых не было в первой итерации, и за счет этого находим хорошее решение, которое сразу бы не нашлось</p><p>В конечном счете мы смогли докрутить все параметры так, чтобы работало как часы.</p><h2>Упаковка в продукт</h2><p>Маршрутизация отдельно от всего, может быть прекрасным продуктом, но, если клиент не может это «поженить» со своими внутренними программами, если водители игнорируют использование приложения, нужно придумывать кастомные интеграции или делать продукт настолько полезным, что клиент сам побежит менять свою внутрянку так, чтобы можно было нормально синхронизироваться со всем остальным. Даже если это будет болезненно.</p><p>Как заставить клиента менять привычный метод «на коленке»? Мы добавили водителей.</p><p>Представим себе логиста, его задача не просто построить маршрут и сделать так, чтобы доставка доехала до клиента, но и решать кучу сопутствующих проблем, таких как: где найти авто, когда пиковая нагрузка и своих не хватает, как заменить и перегрузить груз, если поломка, это все «оффлайн» проблемы, которые можно решать имея Uber модель в перевозках.</p><p>Таким образом, мы предложили full package услуг, маршрутизация плюс авто, логисту остается нажать несколько кнопок, маршрут построится, водитель найдется, отчеты придут, форс мажоры решатся.</p><p>Какие технологии мы использовали для создания такого продукта?</p><p>UI построили с помощью Typescript и кастомного UI фреймворка; этот подход упростил разработку мобильного приложения для водителей с использованием Apache Cordova. Бэкэнд реализовали на Scala и NodeJS (последний для более микросервисного подхода).</p><p>У нас используется множество внешних сервисов, такие как Firebase (для отправки push-уведомлений в Android-приложение); Контур помогает надежно обмениваться юридическими документами с B2B клиентами, Voximplant для организации управления звонками и подмены телефонных номеров; Smsaero для отправки уведомлений о выполнении заказов, с Банком 131 сделана API интеграция по массовым автоматическим выплатам исполнителям.</p><p>Все это позволяет нам к минимуму сводить человеческий труд.</p><h2>Про водителей или без чего не будет успеха</h2><p>Бизнесы по модели маркетплейса это всегда весы, когда нужно искать баланс. Мало заказов — водители моментально уходят и перестают использовать предложение, много заказов- водители находят в других приложения более выгодные/удобные по геолокации заказы и могут в последний момент отказываться от уже взятого.</p><p>Работа с водителями это большой продукт, которым нужно заниматься, продумывать систему обучения, мотивации и штрафов для водителей. Срыв поставки для B2B клиента это, как правило, потеря денег, репутации и клиент скорее всего к вам не вернется. Поэтому, от того, насколько лояльные водители будут работать в вашем сервисе зависит 80% успеха.</p><p>В завершении хочется сказать, что, собирая команду на логистический стартап, важно, чтобы у вас были не только айтишники, но и ребята с опытом в хардкорных классических ТК (транспортных компаниях).</p><p>Мы когда начинали, считали, что опыт таких сотрудников только помешает развитию бизнеса и мы будем делать те же ошибки, что и обычные компании без какого-либо софта, с диспетчером на телефоне. Оказалось, не совсем так.</p><p>В грузоперевозках работа с автопарками ГАЗелей в нашей модели, была несущественная, мы работаем с водителями напрямую. Это стратегическое решение, которое помогает держать цены ниже рынка. Когда у тебя 2000 водителей важно найти ключик, который поможет выяснить мотивацию, и, она, у ГАЗелистов не только денежная.</p><p>Что именно ими движет, как раз расскажут те, кто работал диспетчерами в компаниях со своим парком, с привлеченным транспортом, кто умеет сделать дисциплину водителей частью бизнеса процесса в компании. Так что, собирайте людей с разными скилами, общайтесь больше с клиентами и, возможно, вы сможете занять свою нишу в грузоперевозках.</p>]]></content:encoded>
    </item>
    <item>
      <title>Стек технологий, используемый в работе с Java Virtual Machine</title>
      <link>https://tproger.ru/articles/stek-tehnologij-ispolzuemyj-v-rabote-s-java-virtual-machine</link>
      <comments>https://tproger.ru/articles/stek-tehnologij-ispolzuemyj-v-rabote-s-java-virtual-machine?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Arenadata]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/stek-tehnologij-ispolzuemyj-v-rabote-s-java-virtual-machine</guid>
      <description><![CDATA[<p>Подборка инструментов, библиотек и фреймворков, на которых в Arenadata создают утилиты и интеграционные решения на Java и Scala.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/stek-tehnologij-ispolzuemyj-v-rabote-s-java-virtual-machine">Стек технологий, используемый в работе с Java Virtual Machine</a>»</p>]]></description>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Инструменты]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Фреймворки и библиотеки]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 06 Apr 2021 12:01:45 GMT</pubDate>
      <content:encoded><![CDATA[<p><i>Подборку подготовил Дмитрий Плужников, директор департамента прикладных разработок Arenadata </i></p><p>Мы — IT-вендор, разрабатывающий собственные продукты на базе Open Source проектов (Greenplum, Hadoop, Apache Kafka, Apache NiFi, ClickHouse и др.). В этом кратком обзоре речь пойдёт об инструментах и технологиях, которые используются в нашей компании для создания утилит и интеграционных решений на Java/Scala.</p><h2>Технологический ландшафт</h2><ul><li><b>Apache ZooKeeper </b>— сервер для высоконадёжной распределённой координации приложений;</li><li><b>Apache Spark</b> — фреймворк с открытым исходным кодом для реализации распределённой обработки неструктурированных и слабоструктурированных данных, входящий в экосистему проектов Hadoop;</li><li><b>Apache Kafka </b>— распределённый программный брокер сообщений;</li><li><b>Apache NiFi</b> — ETL-инструмент с открытым исходным кодом;</li><li>ClickHouse — колоночная аналитическая СУБД (Яндекс);</li><li><b>Tarantool </b>— система управления in-memory БД (база данных) с неблокирующим сервером (Mail.ru Group);</li><li><b>Greenplum </b>— массивно-параллельная СУБД для хранилищ данных на основе PostgreSQL.</li></ul><h2>Инструменты</h2><ul><li><b>YourKit Java Profiler</b> — для профилирования процессора и памяти Java;</li><li><b>SonarQube</b> — для анализа качества программного кода;</li><li><b>Git </b>— система управления версиями;</li><li><b>SBT </b>— система автоматической сборки для Java и Scala;</li><li><b>Apache Maven и Gradle </b>— для автоматизации сборки проектов;</li><li><b>Jenkins </b>— для обеспечения процесса непрерывной интеграции программного обеспечения;</li><li><b>Portainer </b>— для управления Docker-контейнерами;</li><li><b>Docker </b>— программа для автоматизации развёртывания и управления приложениями и контейнеризации приложений;</li><li><b>Docker Compose</b> — для запуска и управления Docker-контейнерами.</li></ul><h2>Библиотеки и фреймворки</h2><ul><li><b>Spring Framework</b> — универсальный фреймворк как основа для наших Java-приложений;</li><li><b>Lombok </b>— проект по добавлению дополнительной функциональности в Java c помощью изменения исходного кода перед компиляцией;</li><li><b>Vert.x </b>— фреймворк для реализаций реактивных сервисов;</li><li><b>Apache Calcite</b> — фреймворк для синтаксического анализа и построения SQL-выражений, а также для планирования запросов;</li><li><b>JUnit</b> — фреймворк для написания юнит-тестов;</li><li><b>Akka, Akka HTTP, Akka Streams</b> — набор инструментов для создания параллельных, распределённых и отказоустойчивых приложений для Java и Scala;</li><li><b>Finagle </b>— расширяемая RPC-система от компании Twitter для построения высоконагруженных систем;</li><li><b>ScalikeJDBC </b>— библиотека для доступа к БД с помощью JDBC;</li><li><b>ScalaTest, TestContainers</b> — для написания unit и интеграционных тестов;</li><li>Spark (Core, Streaming, SQL) — для реализации коннекторов к различным источникам данных.</li></ul><p>Для работы с фреймворком Spring также может быть полезен Spring Boot. Это проект, который упрощает создание приложений на основе Spring.</p><p>У нас есть статья, которая <a href="https://tproger.ru/articles/spring-boot-bystroe-znakomstvo-i-start-na-primere-prostogo-veb-prilozhenija/">знакомит со Spring Boot на примере разработки простого веб-приложения</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>ООП паттерн Visitor — объяснение и пример использования</title>
      <link>https://tproger.ru/articles/oop-pattern-visitor-objasnenie-i-primer-ispolzovanija</link>
      <comments>https://tproger.ru/articles/oop-pattern-visitor-objasnenie-i-primer-ispolzovanija?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/oop-pattern-visitor-objasnenie-i-primer-ispolzovanija</guid>
      <description><![CDATA[<p>Классический пример наследования прямоугольника и квадрата показывает, какие ожидания пользователя нарушаются при изменении ширины и высоты фигур.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/oop-pattern-visitor-objasnenie-i-primer-ispolzovanija">ООП паттерн Visitor — объяснение и пример использования</a>»</p>]]></description>
      <category><![CDATA[Паттерны проектирования]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 31 Mar 2021 09:30:35 GMT</pubDate>
      <content:encoded><![CDATA[<h2>Полиморфизм и LSP</h2><p>Рассмотрим классический пример наследования, когда требуется реализовать два класса типа «Прямоугольник» и «Квадрат». Известно, что у каждой фигуры есть периметр и площадь. Будем считать, что объект мутабельный (mutable ― изменчивый) и имеет соответствующие методы (свойства) для изменения размеров. Достаточно легко обобщить формулу для вычисления площади и периметра таких фигур, и, кажется, логично будет использовать наследование. Кто в такой модели должен быть родительским классом, а кто ― потомком?</p><p>Казалось бы, со школы мы помним, что квадрат ― частный случай прямоугольника, а значит, квадрат наследует от прямоугольника.</p><p>Пока все просто. Но что же произойдёт, если мы попытаемся создать «частный случай прямоугольника»? Ведь у квадрата по определению width == height. Конечно же, можно использовать приватную переменную, и при модификации ширины менять и высоту фигуры соответственно, но, если задуматься ― а насколько это ожидаемо? Если квадрат ― наследник прямоугольника, то пользователь должен иметь возможность использовать квадрат точно так же, как и прямоугольник. Может ли пользователь предположить, что при установке ширины прямоугольника автоматически поменяется и его длина?</p><p>Хорошо, если не получается напрямую, давайте попробуем в обратную сторону. Пусть прямоугольник — это такой специальный квадрат, у которого появилась длина.</p><p>Пока выглядит неплохо. Однако, пользователь знает, что площадь квадрата ― квадрат его стороны. Может ли пользователь ожидать, что, установив сторону квадрата в 5, например, он не получит 25 только потому, что его квадрат на самом деле прямоугольник?</p><p>Хорошим дизайном вашей модели будет являться такая, в которой не будет исключений и подводных камней. По идее, только посмотрев на сигнатуру интерфейса, вы должны иметь возможность сказать, как экземпляр этого класса себя будет вести и что от него стоит ожидать. Эта идея носит гордое название «принципа замещения Барбары Лисков» или LSP. Можно грубо сказать, что LSP — это такой ad hoc полиморфизм, при котором класс-потомок никогда не врет.</p><h2>Когда полиморфизм может сделать больно</h2><p>Как известно, полиморфизм — один из «китов», на которых стоит концепция ООП. Сама идея полиморфного состояния настолько мощная и настолько широко используется, что часто можно встретить наследование даже там, где оно и не нужно. Иногда это приводит к нарушению LSP, что может значительно усложнить поддержку существующей кодовой базы. Например, достаточно часто можно встретить реализацию такого вида:</p><p>И ладно, если это часть вашей собственной кодовой базы. Но что, если это некоторый общий модуль, разделяемый между несколькими командами? Или если такой код распространяется в уже скомпилированном виде? Насколько легко будет проверять каждый экземпляр модели на предмет нарушения LSP?</p><p>Подчеркну, что страшно не само по себе нарушение принципа, в конце концов программирование — это раздел инженерии, и вся наша работа состоит в выборе подходящего компромисса — а то, что такое поведение крайне трудно предсказать: откуда разработчику знать, что метод, который он вызовет, выбросит Exception? Обратите внимание, что такое исключение неожиданно и не может быть предсказано исходя из здравого смысла — ведь рядом может лежать другая имплементация, которая не имеет подобной проблемы. Некоторые ЯП имеют checked exception, но практика показывает, что их проще завернуть в unchecked, чем пытаться поддерживать. Как следствие, логическая сложность программы с подобным code smell растет неоправданно, и становится все сложнее понять, какая из N имплементаций сервиса будет работать как ожидается, а какая ― нет.</p><p>При проектировании модели можно услышать советы вроде «придерживайся tell-don’t-ask», «используй null-object-pattern», или даже «prefer composition over inheritance», которые в целом могут помочь увернуться от описанной проблемы. Последний совет, кстати, вообще несколько неочевиден — не использовать наследование в ООП специфичном языке.</p><p>Я предлагаю посмотреть в корень — и он в том, что данные хранятся вместе с поведением. В нашей жизни мы часто думаем об окружающих вещах как об объектах, поэтому такое положение дел кажется более или менее естественным. С другой стороны, при достаточно большой и сложной доменной области наследование может начать нести некоторую опасность ― ведь описать формальным языком поведение, не нарушая LSP, бывает очень сложно. На мой взгляд, эта проблема возникает в первую очередь из-за того, что в реальной жизни мы, скорее, создаем свою иерархию наследований под каждый конкретный случай, тогда как при проектировании доменной области зачастую стараемся сделать из объекта некий «швейцарский нож», обладающий разным и порой никак не связанным друг с другом поведением — потому что чем меньше вспомогательных сущностей мы имеем, тем проще понять модель.</p><h2>«Не узнаю вас в гриме»</h2><p>Вторая проблема более характерна для строго типизированных языков, где, имея список каких-то объектов, приведенных в базовому типу, нужно проверять тип каждого элемента, чтобы вызвать специфическое поведение. Например:</p><p>Такое часто можно встретить при вызове сторонних библиотек, или если у вас legacy. Некоторые языки программирования даже имеют более или менее стандартную функциональность, чтобы работать с базовыми типами, проверяя их конкретную реализацию в рантайме, что ломает сразу двух из трех китов ООП ― и полиморфизм, и инкапсуляцию. Например, если вы счастливый программист на Scala ― у вас есть pattern matching. С другой стороны, никто не мешает сделать своего китоломателя на минималках, и это и есть — Visitor.</p><h2>Идиоматичный Visitor</h2><p>Идея достаточно простая — вместо того, чтобы объявлять поведение внутри класса, мы делегируем это поведение некоторому внешнему объекту. При этом объект-делегат называется посетителем (Visitor), и в нем должны быть объявлены методы посещения для каждого конкретного типа из иерархии. Экземпляр такого объекта мне нравится называть глаголом, описывающим нужный эффект, тем самым подчеркивая, что визитор — скорее поведение, отделенное от данных, чем полноценный объект (makeSomething vs somethingMaker).</p><p>Пора посмотреть, как могла бы выглядеть реализация паттерна:</p><p>Приведенный пример легко можно переделать, чтобы собирать только фастфуд (Sausage) или сериализовать в json, или добавлять любое другое поведение в существующую иерархию объектов. В этом самое большое преимущество паттерна.</p><p>А вот недостатком будет многословность и не слишком большая очевидность. Для каждого потомка Tasty придется делать реализацию visit, а в самом TastyVisitor ― сделать соответствующий метод.</p><p>К тому же этот шаблон не получится использовать, если нет контроля над существующим деревом объектов ― то есть если нельзя внести соответствующие изменения в существующую иерархию.</p><h2>Рекомендация</h2><p>Если у вас уже есть не слишком большая цепочка доменных классов, которые могут использовать в разных сценариях — задумайтесь о том, а не нарушите ли вы принцип единичной ответственности уже сейчас, и не выйдет ли так, что полиморфное поведение будет больше мешать, чем помогать? И если все-таки не хочется иметь разные доменные модели под каждый конкретный сценарий использования, например, потому что они будут на 99% совпадать, то может быть имеет смысл отделить данные от поведения — и Visitor в таком случае может сослужить хорошую службу. Ценой одного дополнительного интерфейса на этапе проектирования и изменением привычного способа взаимодействия с классом модели вы сможете добавлять любое необходимое поведение в типобезопасной манере, и каждый такой метод будет изолирован от других. Получается, что соблюдается и принцип единичной ответственности, и LSP не нарушается.</p>]]></content:encoded>
    </item>
    <item>
      <title>Основы функционального программирования с примерами на Scala — часть 2</title>
      <link>https://tproger.ru/articles/scala-functional-programming-2</link>
      <comments>https://tproger.ru/articles/scala-functional-programming-2?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/scala-functional-programming-2</guid>
      <description><![CDATA[<p>Вторая часть цикла о Scala посвящена гибкой ООП-модели языка — обжектам, трейтам, классам и кейс-классам — и специфичному синтаксическому сахару.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/scala-functional-programming-2">Основы функционального программирования с примерами на Scala — часть 2</a>»</p>]]></description>
      <category><![CDATA[Функциональное программирование]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 07 Oct 2018 17:38:16 GMT</pubDate>
      <content:encoded><![CDATA[<p>В прошлой <a href="https://tproger.ru/articles/scala-functional-programming-1/">статье</a> из нашей серии мы поговорили о том, зачем нужно функциональное программирование, и о недостатках императивного программирования, из-за которых функциональное набирает популярность.</p><p>Кроме того, мы привели базовое введение в Scala, мультипарадигменный язык программирования с широкой поддержкой функционального подхода. В предыдущей статье вы можете ознакомиться с базовыми понятиями языка и узнать, как настроить окружение.</p><p>В этой части мы расскажем об ООП-модели Scala и о некотором синтаксическом сахаре, специфичном для языка Scala.</p><h2>Основы модели ООП</h2><p>Язык Scala имеет достаточно гибкую ООП-модель, состоящую из обжектов, трейтов, классов и кейс-классов, чем-то похожую на таковую в Java.</p><p>Класс в Scala объявляется следующим образом:</p><p>и инстанцируется при помощи конструкции new ClassName(field1, field2, … , fieldN).</p><p>Параметры, введенные скобках после имени класса, являются private полями класса, однако можно изменить их область видимости: если нужно иметь доступ на чтение извне, перед именем поля нужно поставить модификатор val, а если нужно чтение и запись — модификатор var. Классы являются ссылочными типами и неявно наследуют базовый класс AnyRef. Поэтому присваивание объекта с мутирующими (var) полями другой переменной только копирует ссылку.</p><p>В статье будет идти речь о функциональном программировании, поэтому особенности языка, связанные с мутирующими переменными, выходят за рамки обсуждения, как и достаточно подробное описание взаимодействия всех возможных сущностей.</p><p>Внутри класса можно вводить многие вложенные структуры для внутреннего использования. По умолчанию все переменные, постоянные и методы, объявленные в теле класса, — публичные. Их можно защитить при помощи модификаторов private и protected. С другой стороны, вложенные классы недоступны извне.</p><p>Другой ООП-сущностью является trait. В отличие от класса, trait не может иметь конструктора и не может быть инстанцирован. Кроме того, он может содержать абстрактные методы, в то время как класс — только если помечен модификатором abstract.</p><p>Синтаксис трейта таков:</p><p>Ещё одна ООП-сущность, с которой вы столкнулись в <a href="https://tproger.ru/articles/scala-functional-programming-1/">предыдущей статье</a>, — object.</p><p>Его отличительной чертой является то, что он имеет единственный экземпляр, создаваемый автоматически, иначе говоря, является <a href="https://ru.wikipedia.org/wiki/Одиночка_(шаблон_проектирования)">синглтоном</a>. Только обжект может быть точкой входа в программу. Кроме того, вы можете импортировать его вложенные типы, методы, значения в область видимости другого файла. Это позволяет использовать обжект как средство структурной организации программы, давая возможность группировать константы и статические методы.</p><p>Наследование в Scala имеет некоторые особенности. Во-первых, практически всё может наследовать от нескольких trait при помощи синтаксиса extends trait1 with trait2 with trait3 ... with traitN.</p><p>Именно это явление вы видели в начале статьи:</p><p>Здесь App — предопределённый трейт, оборачивающий содержимое внутрь метода main.</p><p>Зачем нужен синтаксис extends … with … with …? Разве нельзя обойтись одним ключевым словом? Увы, нет. Если же разрешить множественное наследование (с наследованием реализации), то появляется <a href="https://ru.wikipedia.org/wiki/Ромбовидное_наследование">проблема ромбовидного наследования</a>. В Scala эта проблема решена определением главного трейта, реализация которого и наследуется. Этот главный трейт идёт первым после слова extends (к слову, это может быть вовсе не трейт, а класс или абстрактный класс).</p><p>Кроме того, вы не можете наследовать типы от объекта.</p><p>На самом деле, вы можете создать анонимный класс-наследник трейта, реализовав все его абстрактные методы используя функционал анонимных классов, и далее создать его экземпляр:</p><p>Но писать такой код бывает достаточно громоздко. Для этого были введены обжекты-компаньоны (companion object). Для них нет специального ключевого слова, поэтому, чтобы их определить, вам нужно создать в файле с классом (или трейтом) обжект с таким же именем, как у класса. У обжекта-комапньона вы можете определить метод apply:</p><p>Тогда вы можете создавать «экземпляры» трейта при помощи синтаксиса Foo.apply(1).</p><p>Этот код громоздкий, поэтому специально для метода apply сделали возможность не писать его название. Эта «магия» работает для всего что называется apply в любой сущности. Выглядит это так:</p><p>Foo(1)</p><p>Подобное можно делать и с классами. Отметим, что семантика метода apply может значительно отличаться от приведённого примера, ведь никто вас не ограничивает в том, что будет делать этот метод. Эта особенность активно используется как в стандартных библиотеках, так и в сторонних.</p><h2>Параметрические типы</h2><p>В Scala есть возможность параметризовать трейт, класс или его метод некоторым количеством типов. Делается это при помощи такого синтаксиса:</p><p>Вы можете использовать параметры типа внутри тела метода/класса/трейта разными способами. Например, вы можете написать функцию, которая будет вычислять композицию 2 функций:</p><p>def compose[U, V, W](f: U =&gt; V, g: V =&gt; W): W = (x :U) =&gt; g(f(x))</p><p>На этом примере мы можем продемонстрировать ещё одну особенность системы типов Scala — она может выводить параметры-типы шаблонов. Например, если мы введём две функции</p><p>то мы можем вычислить их композицию, не указывая цепочку типов:</p><p>val f = compose(fromIntToDouble, fromIntToString)</p><p>Что на самом деле эквивалентно:</p><p>val f: Int =&gt; String = compose[Int, Double, String](fromIntToDouble, fromIntToString)</p><p>Параметрические типы — мощное средство доказательства свойств программы — в том числе типобезопасности. Например, у вас в базе данных хранятся объекты двух типов A и B. Вы не хотите, чтобы кто-то мог добавить объект типа А в коллекцию элементов B (допустим, ваша БД нереляционная, например, MongoDB, и позволяет такое) или же не пытался записать элемент в несуществующую коллекцию. Вы можете написать метод добавления в коллекцию вот таким образом:</p><p>В этом примере вы сможете добавить элемент в коллекцию соответствующего типа. Попытка добавить элемент типа А в коллекцию элементов типа B вызовет ошибку компиляции, и, скорее всего, IDE предупредит вас об этом ещё на этапе написания кода.</p><p>Вы можете создавать псевдонимы для параметрических типов, если вы задали в них все или несколько параметров. К примеру, вы можете ввести список строк:</p><p>type String = List[String]</p><p>Или же, например, кортеж, один из параметров которого — целое:</p><p>type TypInt[T] = (T, Int)</p><p>Хотя на этом возможности системы типов Scala и не завершаются, дальнейшее повествование выходит за рамки нашего введения.</p><h2>Кейс-классы и сопоставление с шаблоном</h2><p>Оператор switch во многих языках воплощает задумку классификации данных на несколько категорий. Но большинство реализаций не могут поддерживать классификацию объектов, и поэтому редко используются в программах. В Scala есть очень мощная система сопоставления объекта с образцом. Однако экземпляр далеко не каждого класса можно сопоставлять с образцом без лишних телодвижений. Для упрощения этого процесса были введены два специальных вида сущностей: кейс-классы (case classes) и кейс-обжэкты (case objects). Кейс-классы подобны именованным кортежам, используемым для хранения данных. Часто они могут не иметь своих методов, выступая пассивными контейнерами, ведь Scala предоставляет великое множество других методов взаимодействия. Итак, синтаксис кейс-класса таков:</p><p>case class CaseClasName(parameterList) { /*опциональное тело класса*/ }</p><p>Все поля кейс-класса немутирующие и публичные. Это не является нарушением принципа инкапсуляции, поскольку он неприменим к публичным параметрам кейс-класса. Инкапсуляция полей имеет место, когда поля класса должны меняться некоторым сложным взаимосвязанным образом, и поэтому изменение полей должно производиться через методы класса. Здесь же нет никакого изменяемого состояния (мы крайне не рекомендуем его вводить в теле класса, чревато неожиданными последствиями), и инкапсулировать нечего. Инстанцировать экземпляр кейс-класса можно удобным синтаксисом:</p><p>CaseClasName(parameter1, parameter2, … , parameterN)</p><p>Примечание Здесь «под капотом» находится автоматически сгенерированный метод apply для этого класса, позволяющий пользоваться таким синтаксисом.</p><p>Пример:</p><p>Второй тип сущностей, case object, похож на case class, но не имеет полей. Зачем же он тогда нужен? Для создания строго типизированных перечислений.</p><p>Заметим, что кейс-класс не может наследовать от другого кейс-класса, поэтому рекомендуем держать иерархию данных как можно более плоской и как можно менее древоподобной. Всегда можно задать кейс-классам общий надтип и, соответственно, нужный набор полей при помощи трейтов. Например, можно сделать так:</p><p>Каким образом работает сопоставление с шаблоном (pattern matching)? При помощи следующего синтаксиса:</p><p>Шаблоны могут быть очень разнообразными в зависимости от используемого типа данных.</p><p>Кейс-класс в сопоставлении с шаблоном можно разложить на его параметры при помощи «вызова конструктора» этого кейс-класса. Например, приведенному выше классу User будет соответствовать шаблон User(name, email). Здесь переменные name и user извлекаются из объекта класса User и после этого становятся доступны блоку value, следующему за =&gt;. Кроме того, вы можете ввести переменную для обозначения объекта, сопоставляемого с образцом, при помощи символа @. Например, такой шаблон введёт переменную user для блока value:</p><p>user @ User(name, email)</p><p>Ещё одной полезной особенностью сопоставления с образцом является возможность зафиксировать некоторые поля класса или же, наоборот, игнорировать некоторые из них.</p><p>Например, мы можем выбирать пользователя только с именем «dave» шаблоном User("dave", email). Если же нам безразличен email пользователя, мы можем не вводить переменную для этого поля шаблоном User(name, _).</p><p>Стоит отметить, что сопоставление с образцами происходит в порядке их расположения. Если шаблон User(name, email) находится выше шаблона User("dave", email), то сопоставления с последним никогда не произойдет, потому что первому из шаблонов соответствует любой экземпляр класса User.</p><p>Если же вам не нужны поля класса, а нужно просто соответствие по типу, используйте шаблон вида valName: TypeName.</p><p>Кроме того, существует шаблон «_», которому удовлетворяет любой объект.</p><p>Результат сопоставления с образцом — значение, возвращённое из value, приведенное к общему надтипу всех блоков value1, … valueN.</p><p>Если ни одному из шаблонов значение не соответствует, выбрасывается исключение PatternMatchingException.</p><p>Приведем пример, объединяющий написанное выше:</p><p>На самом деле, сопоставление с образцом можно применять не только на кейс-классах. На всех типах-примитивах (числа, строки, символы, …), и типов, для которых определён метод-экстрактор. Например, вы можете сопоставлять строку с регулярным выражением. Просто создайте несколько регулярных выражений и применяйте сопоставление с шаблоном:</p><p>Такие действия можно осуществлять, определяя метод unapply и объект-экстрактор. Подробнее об этом можно прочитать в <a href="https://docs.scala-lang.org/tour/extractor-objects.html">документации</a>. Экстрактор имеет ещё одно полезное применение: с помощью него можно распаковывать кейс-классы и другие классы, имеющие экстрактор, используя точно такой же синтаксис, как вид шаблона в сопоставлении с образцом:</p><p>Хотя сопоставление с шаблоном имеет больше возможностей, о которых вы можете почитать в <a href="https://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html">документации</a>, здесь мы ограничимся только этими.</p><h2>Сахар, сахар и ещё раз сахар</h2><p>В этой части мы опишем дополнительный синтаксический сахар, относящийся к функциям.</p><p>Многие функции стандартной библиотеки Scala принимают в качестве параметра другие функции. Например, у списка (List) есть функция map, которая совершает преобразование над каждым его элементом, сигнатура которой упрощенно выглядит так:</p><p>def map[B](f: A=&gt;B): List[B]</p><p>Допустим, у нас есть список целых чисел и нам нужно прибавить к каждому из элементов единицу. Мы могли бы сделать это при помощи лямбда-выражения:</p><p>И получили бы список:</p><p>List(2, 3, 4, 5, 6)</p><p>Но Scala для подобных случаев имеет более лаконичный синтаксис:</p><p>list.map {_ + 1}</p><p>Здесь на место подчёркивания будет подставлен элемент списка. Сокращение в виде подчёркивания может использоваться в самых неожиданных местах, но общая идея его использования — исключение имени переменной там, где можно восстановить однозначным образом манипуляцию над данными, которую вы хотите описать. Например, там, где требуется функция типа (Int, Int) =&gt; Int, вы можете передать суммирование при помощи синтаксиса _ + _. Однако, не всюду такой сахар будет работать, и тогда нужно будет пользоваться обычными лямбда-выражениями. Лямбда-выражения хорошо работают, когда у функции аргументы не запакованы ни в какие обёртки. Если же мы рассмотрим функцию, принимающую функцию из кортежа целых чисел в целое:</p><p>def f(g: Tuple[Int, Int] =&gt; Int) = ???</p><p>То мы не сможем сделать вызов при помощи удобного синтаксиса:</p><p>f { (i1, i2) =&gt; i1 + i2 } // ошибка компиляции</p><p>Функция должна переводить из одного параметра кортежа в целое:</p><p>f { t =&gt; t._1 + t._2 } // верно</p><p>Но такой синтаксис недостаточно выразителен, поэтому для этих целей существует некоторого вида сопоставление с шаблоном. Вообще, синтаксис case &lt;шаблон&gt; if =&gt; value задает частично определённую функцию (partial function). Частично определённая функция, действующая из некоторого набора данных A в набор данных B, отличается от обычной функции тем, что она может быть определена не для всех возможных значений из A. Например, функция извлечения арифметического квадратного корня является частично определённой для всех вещественных чисел от 0 до +∞. Компилятор Scala умеет определять, является ли частичная функция обычной. Если же он обнаружит, что в сопоставлении с шаблоном вы описали не все случаи, он выдаст вам предупреждение с примером входных данных, которые могут выбросить PatternMatchingException.</p><p>Следующая порция синтаксического сахара Scala — ассоциативность операторов. Оператором в Scala называется нестатический метод, который принимает один параметр. Существует два типа операторов: правоассоциативные и левоассоциативные, если вызывать их через точку, то различия нет, но зато, при использовании сокращенного синтаксиса без точки, семантика записи a op b меняется. Правоассоциативные операторы можно вызывать подобным образом:</p><p>a1 op1 a2 op2 a3 … opN-1 aN</p><p>Что эквивалентно записи:</p><p>( ... ((a1.op1(a2)).op2(a3)) …).opN-1(aN)</p><p>Что вполне неплохо сокращает количество скобок. К примеру, мы можем последовательно вызывать метод преобразования элементов списка:</p><p>List(1, 2, 3) map { _ + 1 } map { _ * 2 } map { _ - 1 }</p><p>И это будет эквивалентно записи:</p><p>((List(1, 2, 3).map { _ + 1 }).map { _ * 2 }).map { _ - 1 }</p><p>Левоассоциативные операторы можно вызывать похожим способом:</p><p>a1 op1 a2 op2 a3 … opN-1 aN</p><p>Но это будет эквивалентно совсем другой записи:</p><p>(...((aN.opN-1(aN-1)).opN-2(aN-2))...).op1(a1)</p><p>Левоассоциативные операторы отличаются от правоассоциативных наличием символа «:» на конце. Например, вы можете создавать список, вызывая метод пустого списка (Nil) :::</p><p>1 :: 2 :: 3 :: 4 :: 5 :: Nil,</p><p>что будет эквивалентно:</p><p>((((Nil.::(5)).::(4)).::(3)).::(2)).::(1)</p><p>И создаст список:</p><p>List(1, 2, 3, 4, 5)</p><p>Для унарных и некоторых бинарных операторов существует постфиксная нотация, например, когда у вас нет никаких параметров к методу, вы можете написать value methodName вместо value.methodName.</p><p>Так, например, в стандартной библиотеке в пакете scala.concurrent.duration устроены конструкторы промежутков времени. Вы можете написать:</p><p>На самом деле, вы будете вызывать методы:</p><p>Другое дело, что у обычного Int нет методов second, minutes и milis. Эти методы добавлены к нему при помощи специального механизма методов расширения, о которых мы поговорим в следующей части.</p><p>Некоторые разработчики критикуют возможность создания DSL (Domain Specific Language) прямо внутри языка. Один из основных пунктов критики — код становится непонятным и нечитаемым, разобраться в стрелочках и прочих закорючках становится довольно сложно.</p><p>На самом деле эта критика происходит из неправильного использования DSL: разработчики пытаются создавать предметно-специфический язык, чётко не выделив предметную область.</p><p>Для того чтобы строить полезные и понятные DSL, нужно строго определить область, для которой создаётся язык. Например, стандартная библиотека предоставляет DSL для работы с последовательностями. Далее нужно использовать отличимые и интуитивно понятные символы, и если таких нет, не стесняться использовать слова. Например, использовать -~&gt; и ~-&gt; в одном языке — не самая хорошая идея.</p><p>На самом деле, правильно написанные DSL позволяют сильно сокращать количество написанного кода и делать его более идиоматическим.</p><h2>Заключение</h2><p>В этой части мы довольно подробно рассмотрели, то как устроена ООП система языка Scala. В следующей части мы рассмотрим неявные преобразования, неявные параметры и неявные значения, а также важный конструкт функционального программирования — тайп класс. Кроме того, мы заглянем в стандартную библиотеку и посмотрим, как можно делать хорошо известные вещи, но в функциональном стиле.</p>]]></content:encoded>
    </item>
    <item>
      <title>Основы функционального программирования с примерами на Scala — часть 1</title>
      <link>https://tproger.ru/articles/scala-functional-programming-1</link>
      <comments>https://tproger.ru/articles/scala-functional-programming-1?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/scala-functional-programming-1</guid>
      <description><![CDATA[<p>Настройка окружения, ввод переменных и функций в Scala, а также преимущества функционального подхода перед привычным императивным кодом и ООП.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/scala-functional-programming-1">Основы функционального программирования с примерами на Scala — часть 1</a>»</p>]]></description>
      <category><![CDATA[Функциональное программирование]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 14 Sep 2018 16:43:10 GMT</pubDate>
      <content:encoded><![CDATA[<p>Вы наверняка слышали о функциональном стиле программирования, о таких языках как Haskell, Erlang, Scala, F#, OCaml. Для многих из вас эти технологии могут показаться модной выдумкой для IT-хипстеров или же очень непонятной вещью, отсутствующей в реальном мире. На самом деле, эти языки программирования, как и функциональный подход в целом, предоставляют программисту свои преимущества (выходящие за рамки лямбда-выражений) для написания реальных программ, .</p><p>Большинство приложений в мире написано в традициях ООП (объектно-ориентированного программирования) и использует императивный код. Несмотря на то, что объектно-ориентированный подход очень популярен и прост для понимания, он не лишён своих недостатков.</p><h2>Недостатки ООП</h2><p>Во-первых, в большинстве языков высокого уровня обработка ошибок реализована с помощью механизма исключений. Идея о том, что выполнение кода нужно прерывать, как только достигнуто некорректное состояние, хороша, но её реализация в виде выброса исключения и перехвата его в другом месте требует от коллектива программистов железной дисциплины. Иначе простая линейная цепочка вычислений превратится в древообразную, а то и в запутанный граф. Функциональная парадигма предоставляет абстракции для простой и прозрачной обработки ошибок.</p><p>Во-вторых, императивный код подобен тому, как человек представляет себе порядок каких-то действий. Такой подход очень хорош для описания последовательных вычислений, однако в современном мире большинство приложений асинхронные и многопоточные, и здесь уследить за взаимодействием императивного кода, выполняющегося во многих потоках, очень сложно. Наверное, каждый программист сталкивался с ситуациями, когда два потока пытаются изменить одно и то же значение, или же когда один поток ждёт другой поток, а тот, в свою очередь, ждёт первый?</p><p>В-третьих, не существует математически строгой, аксиоматизированной и пригодной к повседневному применению теории, описывающей паттерны проектирования и систему типов. Паттерны проектирования — это, конечно, большой шаг в сторону стандартизации способов проектирования, но и они — скорее сборник советов и указаний, нежели строгая теория. Исходя из этого, комбинируя паттерны, вы никогда с полной уверенностью не будете знать, что получите в итоге, если вы не делали этого ранее, что, в свою очередь, ведёт к разного рода «неожиданностям» при разработке.</p><h2>Функциональный подход</h2><p>В функциональном программировании решили подойти с другой стороны. Во-первых, решили отказаться от возможности изменять переменные настолько, насколько это возможно (существуют фундаментальные ограничения, не позволяющие сделать это полностью). Функция в смысле информатики не является функцией в смысле математики: например, функция датчика случайных чисел (на основе физического датчика) не является математической функцией — она не принимает параметров, и потому, с точки зрения математики, должна быть константой, но каждый раз эта функция выдаёт разный результат. Такого в математике не бывает. Если же мы запретим переменным изменяться, то есть уничтожим глобальное изменяемое состояние, то функции станут действительно математическими, и можно будет построить строгую математическую теорию. Такая теория была построена и ныне носит название λ-исчисления. Эта теория описывает типы и полиморфизм.</p><p>Математиками-топологами была построена достаточно абстрактная теория категорий, которую они использовали для сокращения доказательств. Со временем теория категорий нашла своё применение во множестве отраслей математики. Информатики выяснили, что эта теория подходит для описания операций с реальными данными, которые не всегда могут быть корректными. Например, понятие монады можно применить для описания вычислений, которые могут привести к ошибке.</p><p>Монады бывают двух видов. Первый вид — «чистая» монада, она представляет корректные данные. Второй вид — некорректная монада, она нужна для представления некорректных данных. Над этими двумя типами данных определены операции:</p><ol><li>pure — функция создания «чистой» монады.</li><li>flatMap — применение преобразования, которое может привести к некорректному результату. К примеру, операция деления целых чисел будет корректно обрабатывать все данные, кроме деления на 0. В этом случае будет создана некорректная монада и применение к ней операции flatMap её не изменит.</li><li>map — применение к данным операции, которая не может вызвать исключений по своей природе, например, операции сложения.</li></ol><p>Важно понимать, что функциональное программирование занимает нишу в середине между низкоуровневыми операциями и очень высокими уровнями абстракции — например, такими, как уровень сервисов или приложений. Исходя из этого был создан объектно-функциональный стиль, позволяющий использовать императивный код для низкоуровневых функций, чистый функциональный код в середине приложения и паттерны проектирования и прочие ООП-технологии на наивысшем уровне абстракции. Таким образом, функциональный подход лучше применять не для создания замкнутых систем, а скорее для слоёв приложений и описания бизнес-логики. Именно в таком ключе функциональное программирование и применяется на сегодняшний день — построенное над низкоуровневым императивным кодом, внутри объектных абстракций.</p><p>Для того чтобы приводить жизненные примеры и показывать, зачем нужна та или иная функциональная конструкция, начнём с краткого, но довольно исчерпывающего введения в мультипарадигменный язык программирования с сильной поддержкой функционального подхода — Scala.</p><p>В этой статье будут описаны фундаментальные языковые конструкции и некоторые средства сокращения кода.</p><h2>О Scala</h2><p>Изначально язык Scala был разработан Мартином Одерски (который также работал над Generics в Java и над компилятором Javac) в EPFL. Первая версия языка была выпущена в мир в 2004 году на платформе Java. Нынешняя версия языка (2-я) имеет версии для платформ JavaScript (Scala-js) и под LLVM (Scala Native).</p><p>Изначально многие решения, реализованные в этом языке, были направлены на устранение недостатков языка Java, таких как слабая типобезопасность и отсутствие синтаксического сахара. Притом новый язык сохранил возможность практически бесшовной интеграции с Java — вы можете использовать все библиотеки, написанные на Java, без падения производительности.</p><p>Язык был оценен по достоинству крупными корпорациями: например, он активно используется в Twitter, LinkedIn, Netflix, Sony и других.</p><h2>Установка IDE и SBT</h2><p>Чтобы использовать Scala под платформу Java, вам понадобятся установленные JRE и JDK. Для знакомства с языком разумно использовать IDE <a href="https://www.jetbrains.com/idea/">IntelliJ IDEA Community Edition</a> со специальным плагином Scala Plugin (доступен прямо при установке IDE) и систему построения проектов SBT (есть под большинство ОС, скачивается при создании проекта).</p><p>Примеры из статьи можно запускать, используя онлайн-компилятор <a href="https://scastie.scala-lang.org/">Scalastie</a>.</p><p>Для того чтобы создать ваш первый проект, нужно сделать следующее:</p><p>new project → scala → sbt</p><figure><img src="https://media.tproger.ru/uploads/2018/09/image2.png" alt="" /></figure><p>В меню создания проекта нужно выбрать версию SBT и Scala, последними на момент написания статьи являются 1.2.1 и 2.12.6 соответственно.</p><p>После нажатия кнопки создания проекта IDEA отдаст указание о создании проекта SBT (это можно понять по надписи dump project structure from SBT), поэтому структура папок проекта появится не сразу.</p><p>После формирования проекта вы можете увидеть подобную структуру папок:</p><figure><img src="https://media.tproger.ru/uploads/2018/09/image1.png" alt="" /></figure><p>Нас в основном будут интересовать папка src и её подпапки main/scala и test/scala, а также файл build.sbt. Файл build.sbt описывает всю структуру проекта и используется для определения модулей, подмодулей, управления зависимостями и версиями библиотек. Сюда же стоит дописывать импорты сторонних библиотек.</p><p>В папке main/scala нужно создать new scala class и выбрать там object (о том, что это такое и какую роль он играет в Scala, будет сказано ниже). Обратите внимание, что имя обджекта должно совпадать с именем файла, в котором он расположен, иначе вы можете столкнуться с ошибками при попытке запустить вашу первую программу.</p><p>После создания обджекта вы увидите следующий код:</p><p>В теле обджекта нужно создать точку входа в программу, а именно метод main() (в Scala методы объявляются ключевым словом def), автодополнение IDEA предложит вам сгенерировать метод как только вы начнёте набирать def main. В итоге должен получиться такой код:</p><p>Если же вам не нужны параметры командной строки args, вы можете сократить свой код до:</p><p>Отметим несколько отличительных особенностей: во-первых, в списке параметров сначала идут имена параметров, а потом их типы после двоеточия, во-вторых, тип возвращаемого значения указывается через двоеточие после списка параметров (в Scala все функции всегда возвращают значение, но когда необходимости в этом нет, используется тип Unit — это аналог ключевого слова void, указывающий на отсутствие какого-либо возвращаемого значения).</p><p>Добавив строчку println("Hello world"), вы сможете запустить эту программу, нажав на зелёный треугольник напротив метода main. Если всё сделано правильно, в консоли должна появиться строка «Hello world».</p><p>Мы настоятельно рекомендуем всем любителям чистых текстовых редакторов на этапе знакомства с языком пользоваться IDEA (пусть это и противоречит философии Unix). Scala содержит большое количество достаточно хитрых конструкций, поддержку которых редко когда можно встретить в редакторе. Кроме того, у IDEA есть много полезных языко-специфических функций. С их помощью IDEA может спасти вас от некоторых глупых ошибок ещё во время написания кода.</p><h2>Переменные</h2><p>В языке Scala есть 2 типа переменных — val и var.</p><p>val — это неизменяемая переменная, ей можно присвоить значение только при инициализации. Синтаксис введения постоянной выглядит так:</p><p>val valueName: TypeName = value</p><p>Опять же, как и у параметров функции, имя постоянной находится сначала, а имя типа — после двоеточия, за именем постоянной. В Scala существует продвинутая система типов, поэтому в большинстве случаев вы можете опускать имя типа, компилятор выведет его за вас (IDEA тоже это умеет, поставьте курсор на имя переменной и нажмите Ctrl+Q).</p><p>Для того чтобы объявить переменную, вам нужно использовать ключевое слово var:</p><p>var valueName: TypeName = value</p><p>Как и в случае постоянной, тип в большинстве случаев можно опускать.</p><p>Переменные можно объединять в кортежи при помощи удобного синтаксиса запаковки в кортеж:</p><p>val tuple: (Type1, Type2, ... , TypeN) = (val1, val2, … , valN )</p><p>И распаковки из кортежа:</p><p>val (val1: Type1, … valN: TypeN) = tuple</p><p>Здесь типы тоже можно опускать, сокращая код до:</p><p>val tuple = (val1, val2, … , valN )val (val1, … val2) = tuple</p><h2>Методы</h2><p>Для определения методов используется ключевое слово def. Синтаксис для определения метода выглядит так:</p><p>В определении вы наверняка не увидели слово return. Это потому, что последнее значение в функции является возвращаемым. То же самое касается и оператора if: вопреки принятой в императивных языках логике, оператор if (condition) value_if_true else value_if_false имеет возвращаемое значение, имеющее тип, общий над value_if_true/value_if_false и значение, в зависимости от условия равное value_if_true/value_if_false.</p><p>В функциях не обошлось без синтаксического сахара. Если функция не принимает параметров, то вы можете не писать скобки. Кроме того, можно не указывать тип возвращаемого значения. Как и в случае с переменными, тип будет выведен (в IDEA этот тип будет напечатан фантомным текстом). Ещё одна «сахарная» особенность — если тело метода достаточно короткое и содержит всего лишь одну инструкцию, вы можете не писать фигурных скобок. Например, такой код будет абсолютно корректен:</p><p>def five = 5</p><p>Хотелось бы отметить, что функция может быть значением и при этом будет иметь функциональный тип, который записывается как SourceType =&gt; ResultType.</p><p>К примеру, функция, которая увеличивает число на 1 (здесь num + 1 — возвращаемое значение, а Int — его тип):</p><p>def inc (num: Int) = num +1</p><p>будет иметь тип Int =&gt; Int.</p><p>Тогда мы можем ввести постоянные, значениями которых будут наши функции:</p><p>val incFunc: Int=&gt;Int = inc</p><p>В чём же разница между val и def? Дело в том, что значение val вычисляется однажды и дальше используется при каждом упоминании, а значение типа def вычисляется каждый раз при упоминании. Проверить это можно следующим фрагментом кода:</p><p>Первые две строчки вывода будут совпадать, а вторые две — различаться.</p><p>Если же у функции много входных параметров, тип можно записать так:</p><p>(Type1, Type2, … TypeN) =&gt; ResultType</p><p>К примеру, функция сложения двух чисел:</p><p>def add(a: Int, b: Int) = a+b</p><p>будет иметь тип: (Int, Int) =&gt; Int.</p><p>Если же нам нужно вернуть несколько значений из функции, мы можем воспользоваться упаковкой и распаковкой в кортеж.</p><p>Для функций существует синтаксический сахар, позволяющий создать функцию, не вводя для неё отдельного метода. Он может быть вам знаком, потому как присутствует в других языках:</p><p>(argument_list) =&gt; value</p><p>value вполне может быть блоком, в котором вы можете вводить дополнительные переменные и совершать некоторые действия. Примеры:</p><p>Поскольку для функций существует тип, мы можем создавать функции от функций, то есть функции высшего порядка. Для этого достаточно просто дописать параметру функциональный тип. К примеру, можно написать функцию, которая к двум числам применяет заданное преобразование:</p><p>def transform (a: Int, b: Int, f: (int, Int) =&gt; Int): Int = f(a,b)</p><p>Есть ещё один нюанс, связанный с функциями. Существует 2 семантики передачи параметров: call by name и call by value. Call by value используется по умолчанию: значение сначала вычисляется, а потом передаётся в функцию. Call by name, наоборот, сначала передаётся в функцию, а потом вычисляется в каждом месте упоминания. Для указания этой семантики перед типом ставится знак =&gt;. Продемонстрировать это можно следующим примером:</p><p>Вы должны получить следующий вывод: 1 1 1 2 3 4. Таким образом, если вы хотите передать в функцию генератор случайных чисел, вы должны использовать семантику callByName.</p><h2>Заключение</h2><p>Мы познакомились с основами языка программирования Scala: рассмотрели, как настроить окружение, как вводить переменные, функции. Мы также рассмотрели два вида семантики методов — callByName и callByValue.</p><p>В следующей статье мы рассмотрим объектную модель языка Scala и некоторые особенности, связанные с синтаксическим сахаром.</p>]]></content:encoded>
    </item>
    <item>
      <title>Плагин IntelliJ Scala обновился до версии 2018.2</title>
      <link>https://tproger.ru/news/intellij-scala-plugin-2018-2</link>
      <comments>https://tproger.ru/news/intellij-scala-plugin-2018-2?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Тимур Кондратьев]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/intellij-scala-plugin-2018-2</guid>
      <description><![CDATA[<p>В плагине Scala для IntelliJ IDEA улучшили поддержку неявных преобразований, автозаполнение шаблонов и добавили семантическое подсвечивание.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/intellij-scala-plugin-2018-2">Плагин IntelliJ Scala обновился до версии 2018.2</a>»</p>]]></description>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[JetBrains]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 27 Jul 2018 13:12:52 GMT</pubDate>
      <content:encoded><![CDATA[<p>JetBrains <a href="https://blog.jetbrains.com/scala/2018/07/25/intellij-scala-plugin-2018-2-advanced-implicit-support-improved-patterns-autocompletion-semantic-highlighting-scalafmt-and-more/">опубликовала</a> обзор обновления плагина Scala для IDE IntelliJ IDEA под номером 2018.2. Среди важных нововведений — усовершенствованная поддержка неявных преобразований, улучшенное автозаполнение шаблонов, появление семантического подсвечивания кода и многое другое.</p><h3>Неявные преобразования и использование аргументов</h3><p>В новой версии редактор кода обзавелся удобными функциями работы с неявными действиями:</p><ul><li>преобразования и аргументы могут быть показаны как встроенные подсказки;</li><li>также подсказки появляются, когда неявный аргумент используется явно;</li><li>встроенные подсказки предоставляют навигацию к значению аргумента или декларации функции.</li></ul><figure><img src="https://media.tproger.ru/uploads/2018/07/IM_1.gif" alt="" /></figure><p>Включить встроенные подсказки в Windows можно по сочетанию клавиш Ctrl + Alt + Shift + «+».</p><p>Кроме того, разработчики также добавили информацию о неявных преобразованиях в действие Parameter Info Tooltip (Ctrl/Cmd + P) и научили команду Implicit Arguments Popup (Ctrl/Cmd + Shift + P) показывать тип, структуру и местоположение аргументов.</p><h3>Автозаполнение</h3><p>Обновленный плагин IntelliJ Scala генерирует исчерпывающее соответствие для закрытых типов с наследниками, Java Enums и Scala Enumerators. Более того, список автозаполнения теперь содержит шаблон unapply(...):</p><figure><img src="https://media.tproger.ru/uploads/2018/07/Comp1.gif" alt="" /></figure><h3>Семантическое подсвечивание</h3><p>Новую функцию можно подключить и изменить под свои нужды в настройках редактора IDE. Раскраске подверглись параметры функций и различные типы переменных. Подсвечивание помогает отслеживать определенную переменную или ее изоляции:</p><figure><img src="https://media.tproger.ru/uploads/2018/07/SH.jpg" alt="" /></figure><h3>Scalafmt</h3><p>Разработчики объединили модуль форматирования Scalafmt, существовавший как отдельный плагин, с IntelliJ Scala. Он может использоваться вместо стандартного модуля IntelliJ, и, в отличие от него, не имеет множества вкладок с настройками, а передает их в файле .conf. Определить, какой из этих файлов будет являться активным файлом конфигурации, можно в настройках редактора:</p><figure><img src="https://media.tproger.ru/uploads/2018/07/FMT.jpg" alt="" /></figure><h3>Другие изменения</h3><p>Кроме того, релиз принес множество исправлений и улучшений производительности, с которыми <a href="https://confluence.jetbrains.com/display/SCA/Release+fixes">можно ознакомиться</a> в списке изменений.</p><p>Scala развивается и становится популярнее в том числе из-за того, что он похож на Java и может использоваться в качестве его замены. По результатам майского рейтинга ЯП TIOBE Scala <a href="https://tproger.ru/news/tiobe-may-2018/">вернулся</a> в топ-20 спустя несколько лет отсутствия.</p>]]></content:encoded>
    </item>
    <item>
      <title>Выпущен компилятор Zinc 1.0 для Scala</title>
      <link>https://tproger.ru/news/zinc-1-0-scala-compiler</link>
      <comments>https://tproger.ru/news/zinc-1-0-scala-compiler?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Светлана Хачатурян]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/zinc-1-0-scala-compiler</guid>
      <description><![CDATA[<p>Инкрементальный компилятор Zinc 1.0 анализирует зависимости исходного кода по классам и сокращает сборку Scala-проектов до 40 раз.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/zinc-1-0-scala-compiler">Выпущен компилятор Zinc 1.0 для Scala</a>»</p>]]></description>
      <category><![CDATA[Компиляторы]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 07 Nov 2017 11:59:36 GMT</pubDate>
      <content:encoded><![CDATA[<p>Zinc — это инкрементальный компилятор для Scala. Большинство Scala-разработчиков даже не замечают, что используют его практически ежедневно: в <a href="https://github.com/sbt/zinc">sbt</a>, <a href="https://github.com/pantsbuild/pants">pants</a>, <a href="https://github.com/cvogt/cbt">CBT</a>, <a href="https://github.com/Jetbrains/intellij-scala">IntelliJ</a> и <a href="https://github.com/scala-ide/scala-ide">Scala IDE</a>.</p><p>У этого инструмента единственная цель — максимально сократить время сборки без ущерба для корректности исполнения. При изменении исходного кода Zinc анализирует все зависимости и компилирует подмножество исходных файлов, на которые оказали влияние внесённые правки. Таким образом сгенерированный код получается абсолютно идентичным выходу чистой компиляции.</p><p>3 ноября разработчики представили новую, усовершенствованную версию компилятора — Zinc 1.0.</p><p>Ключевая особенность v1.0 — анализ зависимостей на основе классов. Этот механизм был разработан для более рафинированной обработки зависимостей, исключающей общие случаи излишней компиляции. Сравнительные тесты показали, что новый механизм сокращает процесс сборки до 40 раз.</p><h3>Пример семикратного увеличения скорости</h3><p>И что же в ней такого особенного? Для сравнения были взяты две версии Zinc: 0.13.x и 0.1.x.</p><p>Исходные данные: <a href="http://www.scalatest.org/">ScalaTest</a>, основной модуль которой состоит из 40 377 строк кода на Scala (не считая комментариев и пустых строк).</p><p>Испытание: обычная операция в любой кодовой базе — добавление метода.</p><p>В данном случае стоит задача добавить новый метод к классу с большим числом зависимостей (вроде AndHaveWord в Matcher.scala) после корректного «разогрева» компилятора и компиляции проекта.</p><p>Насколько быстро с этим справится v0.13.x?</p><figure><img src="http://www.scala-lang.org/resources/img/blog/zinc-0.13-scalatest.gif" alt="" /></figure><p>Инкрементальная компиляция заняла у нее 21 секунду. Настала очередь нового алгоритма.</p><figure><img src="http://www.scala-lang.org/resources/img/blog/zinc-1.0-scalatest.gif" alt="" /></figure><p>Эта версия завершила перекомпиляцию всего лишь за 3 секунды. В данном примере Zinc 1.0.0 оказался быстрее своего предшественника в 7 раз.</p><p>Подобные эксперименты дают совершенно разные результаты, зависящие от особенностей Scala и используемой архитектуры. Но главная идея в здесь том, что разработчикам можно смело ожидать увеличения скорости компиляции при решении ежедневных задач. Больше всего от этого выигрывают проекты Scala на основе cake pattern или интенсивного <a href="http://slick.lightbend.com/talks/scalaio2014/Type-Level_Computations.pdf">type-level</a> программирования. По словам тестировавших алгоритм программистов, в некоторых проектах скорость компиляции в Zinc 1.0 превосходила скорость старой версии в 22 раза.</p><h3>Краткий список нововведений</h3><p>В ходе работы над новой версией инкрементального компилятора были выполнены следующие задачи:</p><ul><li>Усовершенствован инкрементальный алгоритм: устранены «узкие места», которые раньше не удавалось скомпилировать до конца;</li><li>Исправлены баги в инкрементальной компиляции Scala bridge и Java;</li><li>Улучшена обработка type-level программ;</li><li>Усовершенствованы старые Zinc API и созданы дружественные API для дополнения недостающего функционала общего доступа;</li><li>Закончена миграция к Scala 2.12. Zinc подготовлен для JDK8;</li><li>Добавлен анализ на основе протокола передачи данных с долгосрочной бинарной поддержкой.</li></ul><p>С полным списком улучшений можно ознакомиться <a href="https://github.com/sbt/zinc/pulls?utf8=%E2%9C%93&amp;q=author%3Ajvican%20is%3Ap://github.com/sbt/zinc/pulls?utf8=%E2%9C%93&amp;q=author%3Ajvican%20is%3Apr">здесь</a>.</p><p>Новая версия Zinc уже доступна в sbt 1.0.</p>]]></content:encoded>
    </item>
    <item>
      <title>Вышла IntelliJ IDEA 2017.1: поддержка Java 9 и Kotlin 1.1, исправления в Java 8 Stream API, а также многое другое</title>
      <link>https://tproger.ru/news/intellij-idea-2017-1</link>
      <comments>https://tproger.ru/news/intellij-idea-2017-1?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/intellij-idea-2017-1</guid>
      <description><![CDATA[<p>Крупное обновление IntelliJ IDEA принесло поддержку Java 9 и Kotlin 1.1, исправления в Java 8 Stream API и улучшения языков и фреймворков.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/intellij-idea-2017-1">Вышла IntelliJ IDEA 2017.1: поддержка Java 9 и Kotlin 1.1, исправления в Java 8 Stream API, а также многое другое</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Android]]></category>
      <category><![CDATA[IDE]]></category>
      <category><![CDATA[Golang]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Kotlin]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Fri, 24 Mar 2017 10:55:18 GMT</pubDate>
      <content:encoded><![CDATA[<p>IntelliJ IDEA 2017.1 теперь <a href="https://www.jetbrains.com/idea/whatsnew?landing/">доступна</a> для скачивания! Помимо исправлений багов это крупное обновление принесло с собой улучшения в работе с популярными языками, фреймворками и встроенными инструментами.</p><h4>Вот самые важные нововведения:</h4><ul><li><b>Java 9</b>: теперь <a href="https://blog.jetbrains.com/idea/2017/03/support-for-java-9-modules-in-intellij-idea-2017-1/">поддерживаются</a> последние сборки JDK 9. Помимо этого, улучшены соответствующие встроенные инструменты. <a href="https://media.tproger.ru/uploads/2017/03/idea_2017_1_java_9_2.png"></a></li><li><b>Java 8</b>: улучшен механизм перехода с циклов for на вызовы Stream API и обратного перехода. <a href="https://media.tproger.ru/uploads/2017/03/idea_replace_stream_with_loop.gif"></a></li><li><b>Асинхронный отладчик</b>: такая новая фича, как асинхронный стек-трэйс, упростит отладку async-кода. Помимо этого, <i>Smart Step Into</i> получил поддержку асинхронного кода и лямбда-выражений, работающих на других потоках.<a href="https://media.tproger.ru/uploads/2017/03/idea_2017_1_step_into_lambda_expression.gif"></a></li><li><b>Улучшение системы контроля версий</b>: лог-панель для Git и Mercurial получила новые опции, история Git стала быстрее и многое другое. <a href="https://media.tproger.ru/uploads/2017/03/idea_2017_1_ignore_imports_and_formatting.png"></a></li><li><b>Поиск</b>: диалоговое окно Find in Path было полностью переработано и теперь в первую очередь показывает мгновенные результаты.<a href="https://media.tproger.ru/uploads/2017/03/idea_find_in_path_short.gif"></a></li><li><b>Spring</b>: <i>Spring Testing</i> получил поддержку <i>Spring Boot 1.4.3</i> и <i>Spring 5.0</i>. Инструменты <i>Spring Data</i> были обновлены до версии <i>2.0</i> (в том числе <i>MongoDB</i>, <i>Redis</i>, <i>Solr, </i><i>KeyValue</i>, <i>Gemfire</i>, <i>Apache Cassandra</i>, <i>REST</i>, <i>Neo4j</i>, <i>Couchbase</i> и <i>Elasticsearch</i>). Также добавлена новая вкладка <i>Data</i>, упрощающая навигацию по репозиторию. <a href="https://media.tproger.ru/uploads/2017/03/idea_2017_1_spring_data_2.png"></a></li><li><b>Gradle</b>: улучшена поддержка <i>Composite Builds</i>.</li><li><b>Kotlin 1.1</b>: в новой версии этого языка <a href="https://tproger.ru/news/kotlin-1-1/">была добавлена</a> поддержка сопрограмм и компиляции в JavaScript-код. <b></b></li><li>Scala: плагин Scala получил крупные улучшения.</li><li><b>JavaScript</b>: добавлены поддержка <i>Vue.js,</i> улучшения в работе с JavaScript, TypeScript, Angular и Jest, а также многое другое.</li><li>Go: <a href="https://www.jetbrains.com/go/">Gogland</a>, новая IDE для языка Go, теперь доступна <a href="https://plugins.jetbrains.com/plugin/9568-go">в виде плагина</a> для IntelliJ IDEA Ultimate.</li><li><b>Инструменты для работы с БД</b>: IntelliJ IDEA теперь позволяет переносить данные и схемы из одной базы данных в другую (да, это работает даже с <i>MySQL</i> и <i>Microsoft SQL Server</i>).</li><li><b>Эмодзи</b>: редактор теперь поддерживает Юникод-символы эмодзи.</li><li><b>Android Studio 2.2.2</b>: это обновление содержит все фичи <i>Android Studio 2.2.2</i>.</li><li><b>Docker</b>: плагин Docker теперь поддерживает Docker for Mac и запускается через unix://.</li><li><b>Windows</b>: доступна 64-битная версия IntelliJ IDEA.</li></ul><p>Полный список изменений в IntelliJ IDEA 2017.1 можно найти на <a href="https://www.jetbrains.com/idea/whatsnew/?landing">страничке обновления</a> на официальном сайте проекта. Также напоминаем, что совсем недавно <a href="https://tproger.ru/news/webstorm-2017-1/">обновилась</a> WebStorm, среда для JS-разработки от JetBrains.</p>]]></content:encoded>
    </item>
    <item>
      <title>Вышел Scala Native 0.1 — Ahead-of-Time компилятор для Scala</title>
      <link>https://tproger.ru/news/scala-native-0-1</link>
      <comments>https://tproger.ru/news/scala-native-0-1?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Иван Бирюков]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/news/scala-native-0-1</guid>
      <description><![CDATA[<p>Первая версия Scala Native собрана на базе LLVM и создаёт нативные исполняемые файлы вместо байткода для JVM, открывая языку новые сценарии.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/news/scala-native-0-1">Вышел Scala Native 0.1 — Ahead-of-Time компилятор для Scala</a>»</p>]]></description>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Open Source]]></category>
      <category><![CDATA[Новости]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 15 Mar 2017 07:04:59 GMT</pubDate>
      <content:encoded><![CDATA[<p>Вчера была выпущена первая версия <a href="http://www.scala-native.org/">Scala Native</a> — <a href="https://ru.wikipedia.org/wiki/AOT-компиляция">AoT-компилятора</a> для языка Scala, созданного на базе <a href="http://llvm.org/">LLVM</a>.</p><h3>И в чём отличие?</h3><p>В отличие от стандартной реализации Scala, которая генерирует байткод, запускаемый в JVM, Scala Native создаёт отдельные нативные исполняемые файлы. Это позволяет использовать язык в тех ситуациях, когда виртуальная машина — не вариант.</p><h3>Список нововведений</h3><p>Вот интересные фичи, которые попали в версию 0.1:</p><ul><li>поддержка Scala (с небольшими семантическими различиями);</li><li>«бесплатная» интероперабельность с нативным кодом;</li><li>поддержка существующих IDE для Scala из коробки;</li><li>интеграция с инструментом для сборки sbt;</li><li>поддержка основных библиотек JDK;</li></ul><p>Больше информации можно найти на <a href="http://www.scala-native.org/">сайте проекта</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как выбрать технологию для большого и не очень большого веб-проекта</title>
      <link>https://tproger.ru/articles/which-technology-to-choose</link>
      <comments>https://tproger.ru/articles/which-technology-to-choose?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Alexey Gorshkov]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/which-technology-to-choose</guid>
      <description><![CDATA[<p>Никита Семенов, CEO SECL Group, объясняет, почему технологии чаще выбирают по субъективным причинам и что нужно знать для объективного выбора.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/which-technology-to-choose">Как выбрать технологию для большого и не очень большого веб-проекта</a>»</p>]]></description>
      <category><![CDATA[JavaScript]]></category>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Веб-разработка]]></category>
      <category><![CDATA[C#]]></category>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Ruby]]></category>
      <category><![CDATA[PHP]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[WordPress]]></category>
      <category><![CDATA[1C-Bitrix]]></category>
      <category><![CDATA[Magento]]></category>
      <category><![CDATA[OpenCart]]></category>
      <category><![CDATA[Материалы от друзей Tproger]]></category>
      <category><![CDATA[Django]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sun, 20 Nov 2016 15:23:25 GMT</pubDate>
      <content:encoded><![CDATA[<p>Рассказывает Никита Семенов, CEO SECL Group</p><p>За годы работы я часто слышал вопросы о выборе технологий для того или иного веб-проекта. Кто-то спрашивает у нас, как у разработчиков, как правильно, а кто-то приходит и просит сделать на какой-то конкретной технологии.</p><p>Проблема в том, что большинство выбирают технологии по субъективным причинам и пока я не слышал достойного и внятного рассуждения, которое позволит выбрать технологию объективно, основываясь на фактах, а не желаниях. Даже немногие IT-шники могут правильно выбрать технологию, ведь для этого нужно: понимать специфику проекта, иметь многолетний опыт разработки на нескольких языках, знать, как устроены подобные проекты и т.д.</p><p>Но прежде, чем что-то выбирать, давайте посмотрим, какие технологии бывают, чем они отличаются и в каких случаях какую технологию выбрать.</p><h3>Как чаще всего выбирают технологию сейчас:</h3><p>1. Она мне нравится<br />2. Знакомый посоветовал<br />3. Прочитал в Интернете<br />4. На этой технологии сделан аналогичный сайт</p><h4>В чем тут проблема:</h4><p>1. Нравится. Очень субъективно. А что, если по требованиям она не подходит? Или на ней очень дорогие и редкие специалисты? Или она вообще умирает?</p><p>2. Знакомый. Обычно это тот знакомый, который «чуть лучше» разбирается в ИТ, чем тот, кому он советует. И даже если он программист с опытом, он не может знать всех решений на всех популярных языках. Ведь никто не спрашивает, по каким критериям выбирал этот знакомый. Если этот знакомы не CTO Google, я бы так просто не доверял такой рекомендации.</p><p>3. Прочитал. Тут уже лучше, можно найти разные сравнения и аргументацию. Но опять же, чтобы разобраться во всех решениях человеку, пусть даже с крепкими знаниями в разработке, нужно время. А без знаний в разработке все прочитанные технические обзоры ничего не стоят.</p><p>4. Аналог. Большинство популярных сайтов написаны на тех или иных технологиях потому, что так «исторически сложилось» . Если бы Facebook сейчас выбирал технологию для себя, я сомневаюсь, что он взял бы за основу PHP. А еще может быть, что технология уже устарела, её продавили на основе прошлых 3х пунктов, выбрали какую-то разрекламированную технологию, а не действительно эффективную и т.д. Вы вряд ли можете знать реальные причины выбор технологий в других проектах. Оптимальные технологии используются крайне редко в аналогичных проектах.</p><p>Таким образом, ни один из вышеперечисленных методов выбора технологий разработки не отвечает критериям объективности. Поэтому стоит сначала определить эти критерии, а уже потом подбирать по ним техническую платформу. Ниже я попытаюсь выделить действительно важные для проекта критерии, на которым мы и будем основываться.</p><h4>Важные критерии при выборе технологий:</h4><ol><li>Размер и тип проекта</li><li>Сложность проекта</li><li>Скорость разработки</li><li>Стоимость специалистов</li><li>Доступность специалистов</li><li>Доступные инструменты разработки</li><li>Наличие готовых решений</li><li>Гибкость решения</li><li>Наличие широкого сообщества</li><li>Отказоустойчивость решения</li><li>Тренд его развития</li><li>Наличие подробной документации</li><li>Стоимость поддержки</li><li>Требования к нагрузкам</li><li>Требования к безопасности</li><li>Кроссплатформенность</li><li>Возможности интеграции с другими решениями</li></ol><p>Выбирая технологию по таким критериям мы сможем добиться объективного выбора и тем самым сэкономить себе время и деньги.</p><h3>Какие бывают проекты</h3><p>К технологиям мы еще вернемся, а пока давайте разберемся, какие бывают проекты. Часто тип проекта говорит сам за себя и можно сразу сказать, что подойдет: либо уже готовое решение, либо хотя бы в какую сторону нужно двигаться.</p><h4>Сложность проекта</h4><ol><li>Простые (визитки, лендинги, простые интернет-магазины, простые приложения) — такие решения обычно делаются на тематических коробочных решениях, CMS или шаблонах.</li><li>Средние (сложные интернет-магазины и маркетплейсы, порталы национального масштаба, разнообразные сервисы, продвинутые приложения) — такие решения обычно делаются на фреимворках.</li><li>Сложные (огромные порталы, социальные сети, инновационные и нетиповые решения) — ядро таких проектов обычно разрабатываются на чистом (нативном) языке программирования.</li></ol><p>По тематике: интернет-магазины, доски объявлений, социальные сети и т.д. Для большинства популярных тематических решений уже давно есть коробочные продукты и, если мы не пытаемся сделать какого-то монстра, то правильнее будет выбрать именно их. Решений очень много, все в одной статье описать невозможно.</p><h4>Языки программирования</h4><p>В технологиях я бы выделил 3 уровня абстракции:</p><ol><li>Чистый язык — это материал, из которого можно сделать все, что угодно. Ограничивают нас только возможности языка. На чистом языке сделаны все крупнейшие сайты мира с посещаемостью в сотни миллионов и миллиарды пользователей, такие как: Instagram, YouTube, Pinterest, Tumblr, Dropbox, Twitter, Facebook, Amazon, Digg, LinkedIn и другие. Более того, крупнейшие проекты в мире даже создают новые технологии для себя, так как уже существующие их не устраивают.</li><li>Фреимворк — это некая среда разработки для программиста с готовыми правилами и инструментами. Фреимворк с одной стороны помогает и ускоряет разработку, а с другой накладывает определенные ограничения. На фреимворках делаются проекты средней сложности с посещаемостью в миллионы.</li><li>CMS — это уже готовое решения, конструктор, в котором мы по частям собираем нужный проект. Его скорее не программируют, а настраивают. Ограничений тут огромное количество, выйти за границы коробки сложно и неэффективно. На CMS делаются простые сайты с посещаемостью до миллиона пользователей в месяц.</li></ol><p>Чаще всего один уровень абстракции базируется на другом. То есть на чистом языке делают фреимворки, а на фреимворках делают CMS. Для каждого популярного языка есть много разных фреимворков и CMS, но об этом позже.</p><p>Сегодня есть огромное количество разных языков программирования, на которых делают сайты. И, более того, на всех популярных языках есть примеры огромных сайтов. Если 10 лет назад, говоря о технологиях больших сайтов, все говорили преимущественно про Java, то сегодня это может быть почти любой язык и утверждать, что сайты делаются на каком-то конкретном языке — стереотип. Это связанно с развитием самих языков, за последнее десятилетие многие сильно продвинулись в развитии и получили широкие возможности. Конечно, каждый язык чем-то отличается и выбирая мы опять же должны руководствоваться объективными критериями с оглядкой на задачи проекта.</p><p>На чистом языке, без использования фреимворков и коробочных решений, пишутся огромные проекты с повышенными требованиями по гибкости, нагрузкам и безопасности. Для таких огромных проектов часто бюджет не играет такого значения, как эффективность. Чем больше проект, тем больше будет требований по гибкости и нагрузкам, а значит, проще писать все с нуля, выделяя на это лучших специалистов, чем если брать какие-то готовые решения, которые непонятно кем писались и непонятно какие проблемы в них скрыты. К примеру, когда речь про небольшой проект с посещаемостью в 10 тыс. человек в день, то нам будет дешевле сделать его на CMS, которая будет потреблять в 3 раза больше ресурсов сервера, поставить дополнительный сервер за 50$ / мес. и оно будет работать. Когда же мы говорим про сайт с посещаемостью в 100 млн. пользователей в день, стоимость добавления серверов у нас будет просто космической, поэтому нам проще и дешевле вложить деньги в разработку решения на чистом языке, которое будет оптимальным именно для конкретного проекта.</p><p>Чем больше проект, тем больше стек технологий, который в нем используется. В огромных порталах может использоваться сразу несколько языков программирования. Опять же, мы приходим к объективным критериям выбора технологий. Часто один язык может хорошо делать одну задачу, а другой — другую. Такие проекты могут быть на столько огромными, что его части могут работать на разных серверах, с разными доменами (поддоменами) и разными технологиями. Не следует боятся винегрета технологий в большом проекте, хотя и допускать его нужно только когда это действительно необходимо, а также помнить, что далеко не все технологии совместимы. Самый яркий пример использования разных технологий — Google. Он на столько большой, что разные его части написаны на C/C++, Java, Python, JS и других языках. Более того, Google активно создает новые технологии, как, например, популярный нынче AngularJS.</p><p>Попробую дать краткую характеристику каждому из популярных языков:</p><ol><li>PHP — его используют в основном для простых и средних проектов. Очень много коробочных решений. Относительно дешевые программисты. Антитренд последних лет, хотя с выходом последней версии языка под номером 7, он получил действительно мощные возможности.</li><li>Python — современный язык, разработка на нем быстрая и качественная. Используют его для средних и больших проектов. Программистов найти проблематично и стоят они не дешево.</li><li>Ruby — современный язык, разработка на нем так же быстрая. Его используют в основном для разработки простых и средних проектов, часто разрабатывают стартапы. Программистов также мало и они дорогие.</li><li>Java — разработка на нем очень долгая и дорогая. Его используют в основном для больших проектов со специфическими требованиями. Однако является самым популярным языком программирования <a href="https://tproger.ru/news/tiobe-march-2016/">в рейтинге TIOBE</a> по состоянию на март 2016.</li><li>C# — аналог Java, также используют для больших проектов, часть в сфере FinTech.</li><li>JavaScript — очень быстро развивается, тренд последних лет и самый популярный язык программирования <a href="https://tproger.ru/news/redmonk-language-ranking-6-16/">в рейтинге Redmonk</a> по состоянию на июнь 2016. Огромное количество наработок и можно писать все, что угодно, даже игры. Его используют для средних и больших проектов, но действительно мощные возможности этот язык получит недавно, потому примеров больших проектов пока мало, специалисты самые дорогие и найти их сложнее всего.</li></ol><p>Я описал самые популярные языки, которые сегодня используются под веб. Есть много новых языков, которые очень быстро растут, в частности Scala и некоторые другие. Но пока они довольно молодые и сырые. Я бы не рекомендовал бежать за модой и писать на них, пока они не разовьются во что-то большее.</p><p>Примеры больших сайтов:</p><ul><li>PHP: Facebook, Вконтакте, КиноПоиск</li><li>Python: Instagram, Pinterest, Reddit</li><li>Ruby: 500px, Groupon, Airbnb</li><li>Java: Ebay, Amazon, Alibaba</li><li>C#: Guru, Stack Overflow, Bank of America</li><li>JS: LinkedIn, Walmart, PayPal</li></ul><p>Эти примеры отлично показывают, что большие сайты могут быть написаны на разных языках, и это нормально. Опять же, приходим к тому, что выбирать технологию нужно под требования, руководствуясь объективными причинами.</p><h4>Фреймворки и платформы</h4><p>Это некая среда разработки для программистов, где есть готовая инфраструктура и ряд готовых функций со стандартными решениями типичных задач. Такой себе полуфабрикат, из которого можно сделать конфетку. На каждом языке есть много разных фреймворков. Есть как общие, которые создавались для разработки любых решений, так и специализированных, под узкие задачи. Например, Sylius — специализированный E-commerce фреймворк на основе Symfony. Также есть те, на которых делаются большие и сложные решения, а другие для этого не предназначены. Ниже я опишу популярные фреймворки для каждого из языков, на которых можно писать большие и сложные решения.</p><p>На фреймворках разрабатываются довольно большие и сложные сайты с уникальным функционалом. Это значительно быстрее и дешевле, чем на чистом языке, но при этом такое решение позволяет разрабатывать действительно сложные вещи и оптимизировать все это под нагрузки. Кроме того, это почти всегда более безопасно, чем любая коробочная CMS. Если вы хотите узнать об этом больше, посмотрите <a href="https://tproger.ru/translations/web-frameworks-how-to-get-started/">материал про веб-фреймворки для начинающих</a>.</p><p>Популярные фреймворки и платформы:</p><ol><li>PHP: Symfony, Laravel</li><li>Python: Django</li><li>Ruby: Ruby On Rails</li><li>Java: Spring</li><li>C#: .NET</li><li>JS: Node.js, AngularJS</li></ol><p>Больше всего фреймворков на PHP и на этом языке есть, из чего выбирать, но действительно функциональных не так много. Меньше на других языках, а на некоторых действительно качественных фреймворков вообще всего один, как у языка Ruby. У Java вообще очень много разных фреймворков для разных целей, и не только для сайтов. Все эти фреймворки ежегодно развиваются, выходят все новые и новые версии, одни фреймворки обгоняют другие. Например, Laravel только в последние несколько лет вышел на первое место по популярности, хотя самые сложные сайты до сих пор делаются на Symfony.</p><p>.NET и Node.js — это целые самостоятельные платформы, которые базируются на определенных языках, но имеют очень широкие возможности.</p><h4>CMS и CMF</h4><p>Это готовое программное обеспечение, которое нужно только настроить, реже — дописать / переписать какую-то из частей. Таких решений очень много на любом языке, но исторически так сложилось, что в основном все популярные CMS сделаны на PHP. Тут дело в развитие языков, раньше простые сайты, для которых и создавались CMS, писались на PHP. Я еще застал те времена, когда CMS почти не было, были скрипты — отдельные готовые части разных сайтов. Позже эти скрипты собирали в коробочный продукт, который был призван решить потребности 90% простых сайтов. Так и получилось, что основные CMS сделаны на PHP. Сегодня CMS на других языках развиваются слабо, потому, что уже есть сильные конкуренты на PHP, а простому сайту язык не играет большой роли, поэтому все смотрят на возможности этих готовых продуктов.</p><p>CMF — если говорить простым языком, это что-то среднее между CMS и фреймворком по возможностям. Обычно CMF используют для самых сложных сайтов из этой категории. Этот подход позволяет избавиться от лишних частей CMS, которые не нужны конкретному проекту.</p><p>CMS бывают разные по назначению: общие, для интернет-магазинов, для блогов и т.д. Разные по условиям использования: платные и бесплатные. Для каждой популярной CMS есть куча разных платных и бесплатных модулей, которые легко подключать и использовать.</p><p>Маленькие сайты, которые в основном нужны для малого бизнеса, почти всегда используют CMS. Это позволяет очень сильно экономить время на разработку. Кроме того, для настройки таких решений не нужны дорогие программисты, обычно это могут делать новички в программировании, по крайней мере саму настройку, если уже нужно писать код, тут сложнее.</p><p>Именно в работе с CMS возникает больше всего непонимание среди конечных заказчиков таких решений. Любая CMS — это тонны готового программного кода, на все случае жизни. В коробочной поставке идут десятки и сотни модулей. Все это очень сильно ограничивает специалистов. Такие решения сильно «тормозят» , они абсолютно не гибкие, их очень легко взломать, особенно бесплатные CMS. Еще часто взламывают CMS через модули сторонних разработчиков, в которых есть критические уязвимости, потому что мы никогда не знаем, какого уровня программист писал тот или иной модуль. То есть любая CMS НЕ рассчитана для большого и сложного сайта. Она не могут выдержать большие нагрузки. Это решение не безопасно, чтобы не говорили разработчики конкретной CMS.</p><p>Я видел решения почти на всех популярных CMS, с многими за более, чем 10 лет работы, пришлось поработать лично. Часть из них популярна в рунете, а часть знают в основном на западе. На используемые в них языки CMS разбивать нет смысла, по причинам, описанным выше. Лучше сказать несколько слов про каждую популярную CMS:</p><ol><li>WordPress — некогда блоговый движок, сейчас на ней делаются почти любые сайты, включая магазины. Одна из самых популярных CMS в мире, есть примеры довольно посещаемых сайтов. На ней часто делают информационные сайты, в том числе разные СМИ. Система бесплатная.</li><li>Joomla! — CMS общего назначения. Качеством особо не отличается, на ней делают очень маленькие сайты и обычно дешевле всех других вариантов, так как именно с этой CMS начинают учиться многие начинающие программисты. Система бесплатная.</li><li>Drupal — это уже CMF для общего назначения, с недавнего времени поставляется со встроенных фреймворком Symfony. Довольно мощная, на ней есть известные сайты, например, официальный сайт Белого Дома. Система бесплатная.</li><li>Magento — самая популярная система управления для интернет-магазинов в мире. Довольно мощная и сложная. В рунете используется редко, в основном на западе.</li><li>PrestaShop — одна из самых популярных CMS для магазинов в мире. Тоже довольно мощная, используют в основном на западе. Система бесплатная.</li><li>OpenCart — еще одна популярная система для интернет-магазинов, но её, наоборот, больше используют в рунете, чем на западе. В основном для маленьких и несложных магазинов. Система бесплатная.</li><li>1С-Битрикс — очень распиаренная CMS общего назначения, номер 1 в рунете. Возможности очень широкие. На ней часто пытаются делать большие и сложные сайты, а после определенного порога в посещаемости переписывают их на других технологиях. Многие считают, что только эта CMS может интегрироваться с 1С, что не является правдой, поскольку все перечисленные CMS из этого списка могут интегрироваться с 1С, для этого у всех CMS есть специальные модули. Система платная.</li></ol><p>Со всеми перечисленными CMS я работал. В основном со стороны разработчика. Точно НЕ рекомендую — Joomla, с остальными можно работать. Для магазинов лучше выбирать специализированные, а не общие CMS. Кроме 1С-Битрикс в рунете есть еще аналогичные коммерческие CMS, они во многом схожи. У каждой из систем есть свои особенности, но все они не предназначены для больших и сложных проектов, главное это не забывать.</p><h4>Шаблоны</h4><p>В последние 5 лет очень активно развивают шаблонные решения. Это еще на одну ступеньку выше, чем CMS. Если CMS — это конструктор и его нужно настраивать, то шаблоны — это уже готовые решения под типовые случаи. Например, в каждом городе есть свои рестораны, такси, клиники и т.д. Для всех этих типов малого бизнеса нужно примерно одно и тоже. Поэтому, можно просто выбрать готовый тематический шаблон, заменить в нем логотип, цвета и контент. При желании такие шаблоны можно дорабатывать по усмотрению владельца.</p><p>Преимущества таких решений в том, что они очень дешевые и их можно запускать моментально. Но при этом, такие решения не учитывают особенностей бизнеса и конверсия будет не очень высокой.</p><p>Есть специальные каталоги шаблонов: TemplateMonster, <a href="https://themeforest.net/?ref=SECL">ThemeForest</a> и др. Часто встречаются онлайн-конструкторы, в том числе тематические: <a href="http://ru.wix.com/">Wix</a>, <a href="https://www.pagecloud.com/">PageCloud</a> и др.</p><h4>Мобильные приложения</h4><p>В мобильных приложениях в последнее время используется два подхода: нативная разработка и кроссплатформенные технологии. Нативная ведется на оригинальных языках программирования, в частности Swift (для iOS, ранее был Objective-C) и Java (для Android). Кроссплатформенных технологий сейчас довольно много, они есть на базе разных языков программирования, в частности: Apache Cordova, React Native и др. Некоторые лучше, некоторые хуже. В любом случае, сложные приложения всегда пишутся на нативных технологиях. С кроссплатформой часто возникают проблемы, вплоть до того, что некоторые функции просто нереализуемы на тех или иных кроссплатформенных технологиях, сильно грузится оперативная память устройства, быстро садится батарея и т.д.</p><p>В этих двух подходах люди тоже часто путаются, пытаясь использовать кроссплатформенные подходы на все случаи жизни. Оно и понятно, ведь кроссплатформа позволяет писать код один раз, который сразу работает и на iOS и на Android, в то время, как на нативных технологиях это минимум в два раза дороже выходит. Однако мало кто знает про возможные дальнейшие проблемы в разработке. Я бы рекомендовал очень тщательно выбирать технологии и кроссплатформу брать только для простых приложений, иначе придется переписывать. Впрочем, кроссплатформенные технологии постепенно развиваются и становятся все лучше, а приложения написанные на них все сложнее.</p><h4>Стек технологий в больших проектах</h4><p>Выше я описал разные языки и фреймворки, которые используются в больших проектах, однако, если присмотреться к действительно большим проектам, там можно найти целый комплекс языков и технологий. Почти все большие сайты используются в основе один язык и еще несколько дополнительных. Тоже самое с базами данных: для одних задач могут использоваться реляционные, а для других нереляционные базы, и все это органично сочетается в рамках одного проекта.</p><p>Выбор технологий зависит от предлагаемой архитектуры проекта. Именно архитектор продумывает основные блоки будущего сайта. Какой язык ляжет к основу, будет ли он нативный или фреймворк, какую систему кэширования выбрать, какие базы данных, как все это связано и т.д.</p><p>Для примера рассмотрим технологии Instagram (данные Insight IT):</p><ul><li>Ubuntu Server 14.04 LTS — основная серверная операционная система</li><li>Python — основной язык программирования серверной части</li><li>Django — фреймворк</li><li>nginx — второй уровень балансировки входящих HTTP-запросов</li><li>gunicorn — WSGI-сервер</li><li>HAProxy — балансировка нагрузки внутри системы</li><li>PostgreSQL — основное хранилище данных</li><li>postgis — поддержка гео-запросов</li><li>pgfouine — отчеты на основе логов</li><li>pgbouncer — создание пула соединений</li><li>Redis — дополнительное хранилище данных</li><li>Memcached — кэширование</li><li>Gearman — очередь задач</li><li>Solr — гео-поиск</li><li>munin, statsd, pingdom — мониторинг</li><li>Fabric — управление кластером</li><li>xfs — файловая система</li></ul><p>И это вполне нормальный стек технологий. Сам Instagram не самый большой и сложный сервис в мире.</p><h4>Стоимость специалистов</h4><p>Один из важнейших факторов выбора технологии является стоимость и доступность специалистов, потому что именно это самая затратная часть в любом проекте. В рунете есть только одна пузомерка по зарплатам — я отфильтровал по Киеву, уровень Senior, опыт 3-5 лет. Сравним средние значения.</p><p>Зарплаты:</p><ol><li>C# — 3072$</li><li>Java — 3300$</li><li>JS — 3500$</li><li>PHP — 2780$</li><li>Python — 3000$</li><li>Ruby — 3000$</li><li>Scala — 3900$</li></ol><p>В США немного другая картина:</p><figure><img src="https://media.tproger.ru/uploads/2016/11/salary.png" alt="" /></figure><p>Теперь переведем цифры на человеческий язык. Java хоть и не новый язык, но специалисты на ней всегда были одними их самых дорогих. PHP всегда был самым дешевым, да и специалистов на рынке очень много. В сравнение я внес еще и Scala как один из новейших и трендовых языков, по этой причине он дороже всех. Еще дорогой JS, это связанно с его бурным ростом в последние годы и растущей популярностью Node.js, а также AngularJS.</p><p>Таким образом, если мы хотим экономить — то лучше смотреть на PHP, специалисты дешевые, а комьюнити большое. А если хотим самое качественное — то смотрим на Scala, который называют будущем веб-разработки, но, правда, на ней найти специалистов почти невозможно и наработок просто нет.</p><p>Еще важным параметром будет скорость разработки. Ведь важна не только зарплата программистов, но и скорость разработки. Если не учитывать уже существующие наработки, то одним из самых быстрых в разработке будет Python и Ruby, а самый медленный — Java. Кстати, по этой причине за последние 10 лет почти не вышло новых мегапроектов на Java, зато вышло много проектов на Python, о чем я расскажу ниже.</p><h4>Тренды</h4><p>Выбирая технологию, нам нужно смотреть вперед. Особенно, если речь о большом проекте. Все технологии очень быстро развиваются, выходят все новые и новые версии. Языки сильно меняются каждые 5-7 лет, фреймворки — каждые 2-3 года, а CMS — каждые 1-2 года. Важно выбрать не просто хорошую технологию сегодня, а предугадать тренды развития так, чтобы остаться на коне через несколько лет. Иначе, в конечном счете, придется переписывать проект, что всегда очень проблематично.</p><p>Есть всевозможные исследования, которые нам могут подсказать некоторые статистические выкладки. Например, исследование <a href="http://www.tiobe.com/tiobe-index/">TIOBE Index</a> показывает интересную статистику:</p><figure><img src="https://media.tproger.ru/uploads/2016/11/tiobe.png" alt="" /></figure><p>По результатам разных исследований можно выделить явных лидеров по росту — это JS (версия ES6 и выше) и мультипарадигмальные языки, в частности Scala. Кстати, именно Scala считается преемником языка Java и во многом на него похож. Также не плохо себя показывает Python.</p><p>Антитренды держат ряд старых языков и PHP. Правда, недавно вышла 7я версия PHP, в которой исправлены многие серьезные недостатки. Так что, я думаю, мы скоро увидим новый виток развития PHP. Еще многие большие проекты переписываются с Ruby на другие языки, тоже некий антитренд.</p><p>Для иллюстрации посмотрим, каких специалистов не хватает в США:</p><figure><img src="https://media.tproger.ru/uploads/2016/11/specialists.png" alt="" /></figure><p>Именно это можно считать реальной картиной трендов, которые мы видим и у нас.</p><p>На чем делались большие проекты за последние 10 лет?</p><ol><li>Airbnb — Ruby</li><li>Instagram — Python</li><li>Pinterest — Python</li><li>Foursquare — Python</li><li>Groupon — Ruby → JS</li><li>Twitter — Ruby → Scala</li><li>Uber — JS</li></ol><p>Это уже не теоретическая статистика, а реальная практика. Python и JS очень хорошо себя показывают.</p><h4>Стоимость поддержки</h4><p>Безусловно, важный критерий выбора технологии — это стоимость поддержки, о которой мало кто задумывается в начале разработки. Обычно все мыслят категориями стоимости часа поддержки, что в корне неправильно. Нам важны несколько параметров: стоимость часа, количество часов, официальная поддержка технологии, доступность специалистов, правильный подход к разработке и некоторые другие.</p><p>Стоимость часа зависит от зарплаты специалисты, с этим мы уже разобрались. А вот количество часов зависит от самой технологии и качества написания кода. Если решение коробочное, то часов на него может уходить очень много. То есть, с одной стороны, мы можем сэкономить при разработке первой версии проекта, но после погрязнуть в его постоянной доработке. Хорошо, когда решение популярное и есть официальная документация, но часто выбирают малоизвестные коробочные решения без какой-либо документации — в таких решениям стоимость поддержки будет во много раз выше стоимости самой коробки. То же касается некачественной разработки: у нас почему-то полностью отсутствует культура проведения технических аудитов готовых решений или его частей. В среднем за 20-40 часов можно проверить почти любое решение и найти его основные минусы. Чем более качественный код, тем легче, а следовательно и дешевле его поддерживать.</p><p>Также следует смотреть на версию языка, фреимворка, CMS. Нужно всегда использовать самую последнюю стабильную версию, чтобы она не устарела до выхода проекта в продакшн. При появлении новой версии, нужно сразу рассматривать возможность перевода проекта на эту версию. Потому что, если пропустить несколько версий, потом будут проблемы сделать резкое обновление.</p><h3>Так что выбрать?</h3><p>Подведем итог. Для простых сайтов чаще всего отлично подходят коробочные решения и шаблоны. Сложные сайты делаются только на фреимворках или даже чистых языках программирования. Делать можно на очень разных языках, язык выбирается под проект. Простые мобильные приложения можно делать на кроссплатформенных технологиях, а сложные обычно делаются на родных технологиях. Ну и, выбирая платформу, всегда стоит руководствоваться объективными критериями, которые я описал в статье.</p>]]></content:encoded>
    </item>
    <item>
      <title>Быстрый старт со Scala для начинающих и не очень</title>
      <link>https://tproger.ru/articles/scala-tutorial-for-beginners</link>
      <comments>https://tproger.ru/articles/scala-tutorial-for-beginners?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Типичный программист]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/scala-tutorial-for-beginners</guid>
      <description><![CDATA[<p>Scala — строго статически типизированный язык на JVM с классами, функциями высшего порядка и обобщениями; для работы нужен установленный JDK от версии 1.6.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/scala-tutorial-for-beginners">Быстрый старт со Scala для начинающих и не очень</a>»</p>]]></description>
      <category><![CDATA[Для начинающих]]></category>
      <category><![CDATA[Scala]]></category>
      <category><![CDATA[Быстрый старт]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Thu, 19 Mar 2015 13:21:31 GMT</pubDate>
      <content:encoded><![CDATA[<p>Scala – строгий статически типизированный JVM-based язык, успешно совмещающий парадигмы объектно-ориентированного и функционального программирования. В языке есть классы, функции высшего порядка, анонимные функции, обобщенное программирование. Использование Java-кода из Scala не вызывает трудностей, синтаксически языки очень близки. В этой статье мы разберем основные элементы языка, достаточные для того, чтобы начать на нем писать.</p><h2>Настройка окружения</h2><p>Scala — язык, работающий на JVM, поэтому для работы требует установленную JDK (минимальная версия 1.6). Ее можно взять <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">отсюда</a>. После установки JDK можно приступить к установке самой Scala. Скачать свежую версию можно на <a href="http://www.scala-lang.org/download/">официальном сайте</a>. Последняя версия на момент написания статьи — 2.11.6.</p><p>Для того, чтобы все корректно работало из командной строки, рекомендуется прописать переменные среды JAVA_HOME и SCALA_HOME, а также дополнить переменную PATH путями к выполняемым файлам. На Linux и MacOS это делается так:</p><p>Для того, чтобы сохранить эти настройки, их надо прописать в ~/.bashrc или ~/.bash_profile.</p><p>На Windows команда немного другая:</p><p>Прописать эти опции постоянно можно в настройках системы: Control Panel → Advanced System Settings → Environmental Variables.</p><p>После выполнения всех манипуляций можно проверить результат, запустив:</p><h3>SBT</h3><p>Простые скрипты и маленькие программы можно, конечно, компилировать и запускать вручную с помощью команд scalac и scala. Однако, по мере того, как количество файлов будет расти, ручная компиляция будет становиться все более нудной. Вместо этого используют системы сборки. Для сборки кода на Scala можно использовать стандартные для Java (неофициально) maven, gradle или ant, но сообщество и сами разработчики рекомендуют <a href="http://www.scala-sbt.org/">sbt</a> (simple build tool).</p><blockquote><i>Примечание</i>: если вы устанавливаете sbt, то можете пропустить отдельную установку scala, так как система сборки скачает ее автоматически</blockquote><p>Описание процесса сборки находится либо в файле build.sbt в корне проекта, либо в файлах .scala в папке project там же. Само описание – это программа на Scala (которая, в свою очередь, может собираться с помощью sbt как отдельный проект, который… ну, вы поняли).</p><p>Синтаксис .sbt-файла напоминает синтаксис Scala с некоторыми дополнениями и ограничениями. Минимальный build.sbt выглядит примерно так (пустые строки обязательны):</p><p>Исходники помещаются в папку src/main/scala и src/test/scala по пути, соответствующем иерархии пакетов (как в Java). Чтобы собрать, протестировать и запустить проект, необходимо в любой поддиректории проекта выполнить следующие команды:</p><p>или через интерактивную консоль:</p><p>Последовательное выполнение команд выглядит немного необычно (обратите внимание на точку с запятой в начале — это особенность синтаксиса):</p><h3>REPL</h3><p>Отличным помощником в разработке будет REPL (Read-Eval-Print-Loop), или по-другому, интерактивная консоль. Очень удобно проверять в ней небольшие функции, отлаживать код или просто посмотреть возможности языка. Для запуска REPL наберите sbt console в командной строке. Вы увидите примерно следующее:</p><p>Все! Можно писать команды на Scala и сразу же их выполнять:</p><p>Для выхода из REPL можно нажать Ctrl+D. Все примеры на Scala далее можно протестировать в REPL, для вставки больших кусков кода можно воспользоваться командой :paste.</p><h3>IDE</h3><p>Использование IDE для разработки на Scala не обязательно, однако сильно упрощает процесс. Скала — язык со сложной семантикой, поэтому возможности IDE более ограничены, чем, скажем, при разработке на Java. Тем не менее даже простая подсветка несуществующих методов и автодополнение существующих может сильно облегчить жизнь. Самые популярные IDE для Scala — это <a href="http://www.jetbrains.com/idea/">IntelliJ IDEA</a> и Eclipse. Для IDEA есть плагин от JetBrains, в случае с Eclipse есть ее вариант Scala IDE.</p><h2>Переменные, значения и типы.</h2><p>В Scala переменные и значения объявляются ключевым словом val или var. val — это неизменяемая переменная (значение), аналог final в Java. var — обычная переменная. Например:</p><p>Аналогичный код на Java будет выглядеть так:</p><p>Здесь мы видим сразу несколько приятных особенностей Scala:</p><ol><li>точка с запятой не обязательна (работает автоматический вывод);</li><li>указания типа переменной необязательно (также работает автоматический вывод типов);</li><li>ключевое слово public подразумевается по умолчанию.</li></ol><p>Типы переменных указываются после имени, через двоеточие. Также в Scala нет, как таковых, примитивных типов (int, float, boolean и т.д.). Их заменяют соответствующие классы Int, Float, Boolean и т.д. Любая переменная — экземпляр какого-либо класса. Иерархия классов начинается с Any, все классы наследуются от него (аналог Object в Java).</p><p>Применение привычных операторов, при этом, на самом деле — вызов метода: a + b тождественно a.+(b). Вариант записи без точки применим к любым методам (с некоторыми ограничениями).</p><h2>Функции, анонимные функции, методы</h2><p>Функция в Scala объявляется с помощью ключевого слова def. Пример объявления и применения функции:</p><p>Аналогичный код на Java:</p><p>Как видно на примере, необязательны не только точка с запятой и указание типа, но и фигурные скобки вокруг единственного выражения и слово return. Более того, его использование считается плохой практикой. Из функции возвращается значение последней выполненной команды.</p><p>На самом деле, функция — это тоже объект. Каждая функция в Scala — это экземпляр класса Function, у которого есть метод apply. Поэтому мы вполне можем записать так (знак подчеркивания ставится на место аргумента функции):</p><p>Вызов метода apply подразумевается по умолчанию, поэтому использование функций внешне выглядит как в Java:</p><p>Все четыре вызова функции идентичны. Представление функций в виде объектов позволяет оперировать с ними, как с остальными объектами: передавать в качестве аргументов, возвращать из других функций, расширять дополнительными методами и т.д., что позволяет Scala полноценно поддерживать парадигму функционального программирования.</p><p>Конечно, присутствуют анонимные функции (лямбда-функции). Они объявляются так:</p><p>Здесь мы объявляем анонимную функцию, которая принимает один целочисленный аргумент и присвоил ее переменной f, после чего применяем f как обычную функцию.</p><h2>Классы и объекты</h2><p>Если вы программировали на Java, многие вещи, касающиеся объектно-ориентированного программирования будут вам знакомы. Класс объявляется ключевым словом class, новый экземпляр — через new. Методы класса — это функции, объявленные в его теле. Поля класса указываются сразу после имени, как список аргументов. При этом, по умолчанию они объявляются как private val. То есть, если мы не укажем никаких модификаторов, указанное поле будет доступно только внутри класса и будет неизменяемым. Класс можно сделать абстрактным, добавив abstract перед объявлением. Основное отличие от Java здесь заключается в отсутствии конструктора. Код, который должен выполняться при создании объекта, пишется прямо в теле класса. Как при этом реализовать несколько конструкторов с различным числом аргументов, мы рассмотрим позже. Пример использования класса:</p><p>И аналогичный код на Java:</p><p>Как видим, public указывать не обязательно, аргументы конструктора доступны во всем классе, локальное приватное поле создавать также не обязательно.</p><p>Кроме того, в Scala мы можем объявить сразу объект, без создания класса, с помощью ключевого слова object. Таким образом реализуется паттерн «Одиночка» <i>(Singleton)</i>.</p><p>Аналог на Java будет куда более многословен.</p><p>В этом примере мы пометили конструктор как protected, чтобы исключить возможность его вызова извне, обращение к объекту будет осуществляться через метод getInstance(), который при первом своем вызове инициализирует экземпляр класс, а при последующих возвращает уже созданный экземпляр. Кроме того, вполне допустимо существование объекта и класса с одним и тем же именем, при этом они делят область видимости. Поэтому необходимость в директиве static отпадает — методы, объявленные не в классе, а в объекте ведут себя как статические. Такой объект называется в терминологии Scala «companion object» («объект-компаньон»).</p><p>Вернемся к конструкторам. Вспомним, что при применении любого объекта к некоторым аргументам по умолчанию вызывается метод apply. Этим мы и воспользуемся и напишем класс с несколькими конструкторами, статическими методами, изменяемыми и неизменяемыми полями в идиоматичном для Scala стиле и продублируем этот же код на Java.</p><p>Вариант Scala:</p><p>Вариант Java:</p><h2>Интерфейсы и трейты</h2><p>Аналогом Java-интерфейса в Scala является трейт (trait). Как ни удивительно, объявляется он с помощью ключевого слова trait. Как и интерфейсы Java, трейты содержат только объявления методов и допускают множественное наследование. В отличие от интерфейса, в трейте можно описывать поля класса и частично реализовывать методы. Наследование как трейтов, так и абстрактных классов осуществляется с помощью extend (первый родитель) и with (последующие родители). Пример использования:</p><p>Ключевое слово override необязательно, но его использование является хорошей практикой.</p><h2>Другие особенности и отличия от Java</h2><p>Как и в Java, в Scala классы, трейты и функции можно параметризовать. Параметры типов пишутся в квадратных скобках после имени класса или функции. Так определяется интерфейс Foo, который принимает некоторый тип A и содержит метод bar? который принимает значение типа A и некоторого типа B и возвращает объект типа C. Конкретные типы A, B и C будут определены в реализации интерфейса.</p><p>Конструкция if/else всегда возвращает значение выражения, которое стоит последним ввыполняемом блоке. Скобки вокруг условия обязательны, скобки вокруг тела, в котором только одна инструкция, можно опустить.</p><p>Блок try/catch/finally выглядит в Scala так:</p><p>Циклы while ничем не отличаются от варианта в Java:</p><p>А циклы for — наоборот, совсем не похожи (о них мы подробнее поговорим в следующей статье):</p><p>Также вы, возможно, могли заметить литерал ???. Он имеет тип Nothing который является подкласс любого класса. При вызове ??? кидает исключение NotImplemented. Это примерно аналог undefined в Python. ??? можно ставить в качестве заглушки вместо тела функции, к написанию которого вы планируете вернуться позже.</p><h2>Заключение</h2><p>Итак, мы установили и настроили среду разработки для Scala, посмотрели основные элементы языка, сходства с Java и отличия от нее. Этого вполне должно хватить для того, чтобы начать писать простой и рабочий код. В следующей статье мы подробнее рассмотрим элементы функционального программирования, case-классы, pattern-matching и другие высокоуровневые особенности языка.</p><h2>Дополнительные материалы и ссылки</h2><p><a href="http://www.scala-lang.org/">Официальный сайт</a><br /><a href="http://www.scala-sbt.org/">SBT</a><br /><a href="http://www.jetbrains.com/idea/">IntelliJ IDEA</a><br /><a href="http://www.scalatest.org/">ScalaTest</a></p>]]></content:encoded>
    </item>
  </channel>
</rss>