А потому что только очень крупным «сертифицированным» агенствам позволено манипулировать общественным мнением. Ибо за ними стоят ну оочень крутые игроки, которым не сильно рады терять деньги. И неча тут всяким со свиным рылом в калашный ряд соваться.
Это CDI ничем не отличается от спринговых бинов — то же, только хуже. А EJB — это более тяжелая технология, которая служит для интеграции с платформой. Почему рудиментарные? Stateless EJB организует пул объектов, которые гарантируют изолированность вызовов, что вобщем-то не требуется, если ваш объект stateless. Statefull вообще непонятно где может использоваться, плюс имеет такую фичу как пассивация объекта через какое-то время и сохранение состояния где-то в дебрях диска. Внезапно происходят exceptions если ваш Stateful не Serializable. Message driven bean до сих пор нет стандартного способа хорошо указать ActivationConfigProperties. Они все vendor-specific. Singleton bean мешает кластеризированию — он, оказывается, всего лишь server instance singleton, а не application singleton. Годная вещь — remote EJB interface. Но она также vendor-specific, и практически всегда непроксируема (только в локальной сетке), поэтому всегда предпочтительней JAX-WS или JAX-RS, чем remote EJB.
И, наконец, очень медленные. Чтобы посмотреть через что проходит ваш простой вызов к EJB, просто сделайте stacktrace…
и вы можете сделать архитектуру именно такой, как вам нужно. Но это при том условии, что у вас неограниченное количество человеко-часов
Подключите фреймворк или библиотеку, которая наиболее подходит задаче. Альтернатив всегда десятки. На крайний случай, практически все, что входит в стек JEE доступно standalone.
и в итоге все равно получиться чуточку хуже, чем то, как это реализовано в современных JEE серверах.
Всегда задаю вопрос: а что такого особенного реализовано в JEE серверах? Какие супер-пупер технологии? Вебстек, альтернатив которому уже десятки? Наихудшая, непонятная и неудобная модель компоновки и запуска приложения, связанная с запаковкой всего в .Xar? Рудиментарный EJB? CDI? Webservices? JDBC pool? JPA? Все это доступно standalone без особого напряга. Правильный ответ дают лишь немногие: это JTA (distributed transactions). Если Вы не используете JMS и в проекте только одна база данных, можете смело забыть о JEE.
Все промахи всплывут только под реальной нагрузкой, и архитектуру приложения придется переделывать не один раз.
До сих пор всплывали промахи, связанные именно с сервером приложений и стеком JEE. Причем в этом случае архитектуру Вы уже сильно не поменяете.
Java.nio для сети
Не успев полностью сесть на JEE вы уже прикручиваете сбоку какой-то левый велосипед, который и близко не лежал к стеку. Если уж Вы рекомендуете JEE, так используйте его средства: http servlets, JMS, Remote EJB, WS… Либо как белый человек пишите свой resource adapter, согласно спецификации. И уж там можете пользовать хоть java.nio, хоть netty…
Если вы пишете пул сами, а не используете готовый в случае JEE, нужно внимательно расставить тайминги.
Если Вы используете готовый, то нужно еще более внимательно расставить тайминги. Weblogic имеет более 100 настроек для пула. Еще надо найти и включить мониторинг для пула, чтобы время от времени выявлять незакрытые ресурсы и впоследствие ломать голову над тем, где в коде происходит leaking.
Они нужны для взаимодействия между потоками,
В JEE нет такого паттерна как «взаимодействие между потоками». Есть асинхронное выполнение, есть асинхронное взаимодействие посредством JMS. Все остальное синхронно.
Не стоит использовать JSP для высоко нагруженной системы, даже с кэшем он будет медленнее сервлетов.
JSP при использовании скриплетов (теги с процентиками) компилируется в .class и работает с той же скоростью, что и сервлет. Если вы используете различные tag libraries (например JSTL и EL), то перформанс будет немного проседать ввиду того, что приходится интерпретировать теги. Однако, вроде бы есть компилятор для JSTL. Если же вы используете JSF, то перформанс падает значительно. JSF — технология не для hiload.
Лучше собирать и писать в базу эти метрики отдельным софтом или самостоятельно.
Опять велосипед. Коммерческие сервера предлагают свои средства для сбора метрик и мониторинга. Это именно то, за что собирают деньги. А уж если мне нужно свой велосипед для мониторинга, то гораздо проще его будет присобачить без JEE.
Дело в том, что сервер следит за своими потоками и отлавливает deadlock
Полная фигня. Сервер не отлавливает ничего. Сама архитектура JEE предполагает отсутствие дедлоков и правильную блокировку. Просто серверный пул конфигурируется и мониторится сервером. Плюс некоторые сервера могут корректно закрывать некоторые оставленные ресурсы типа connections из пулов. И еще корректно закрываться в случае остановки сервера. Недостаток всех пулов: нельзя использовать ThreadLocal (вернее очень осторожно).
В Java шаблон ServiceLocator (java.util.ServiceLoader) используется очень часто, когда нужно подключать различные имплементации публичного API в зависимости от classpath.
С одной стороны это универсальный способ без лишних заморочек использовать различные сервис-провайдеры. Проблемы начинаются когда нужно сконфигурировать конкретный провайдер, ибо для этого не придумано хорошего стандартного способа. Часто это делается либо через system properties, либо через внешний файл конфигурации.
Основной смысл любого языка — выражать мысли. Хороший язык позволяет писать в терминах максимально близких к решаемой задаче. Java в этом плане нехороший язык. Например для описания простого property в Java Bean нужно имя написать 6-8 раз. Кроме того основная проблема Java — он семантически не расширяем. На основе него нельзя создать свой метаязык (domain-specific language), описывающий термины предметной области (с этим плохо пытаются справиться frameworks+annotations). Поэтому существуют такие JVM-языки как Groovy, Kotlin, Xtend, Gosu, Ceylon, которые призваны исправить некоторые недостатки Java, оставаясь в рамках совместимости и интероберабельности. Ибо компилироваться в JVM и игнорировать экосистему Java просто глупо — язык станет ненужным.
Теперь о Scala. Она изначально вообще задумывалась быть независимой от рантайма. Первые версии компилировались в JVM и .NET. Но по какой-то причине с .NET не сложилось — теперь это полудохлый независимый проект. Так что по меньшей мере некорректно говорить о Scala как продолжение Java, о чем собственно и заявляют создатели.
Какова же цель создания Scala? Со слов Одерски, он мечтал сделать единый универсальный гибкий и расширяемый язык (lingua franca) для всего, на котором можно было бы описывать предметные области и создавать собственные языки (DSL). За основу концепта была взята Java с примесью ФП и кучей сахара. Для семантического расширения языка предусмотрена мощная система типов, которая, в прочем, плохо ложится на ООП-core, в отличие от того же Haskell-а, в котором ООП не зашит в язык, а выводится искусственно. Ради расширяемой семантики язык загромоздили тоннами синтаксического сахара, implicit-ов и соглашений. Но вскоре поняли, что и этого недостаточно. Взляд создателей пал на Nemerle, который культурно предоставлял метапрограммирование через AST и макросы. Кому-то очень понравилась идея, а также душила жаба, что подобной фигни еще нет в scala. Поэтому вот вам: scala.meta, scala.macros.
Теперь о вашем вопросе: смысл Scala? Для истинных ценителей ФП есть красивейший Haskell. Как показывает практика, на скалу переходят именно искатели лучшей джавы, вопреки тому, что она для этого изначально не задумывалась. А для чего задумывалась? Сразу для всего в общем, и ни для чего в конкретике.
Согласен. И все-таки, я склоняюсь, что Scala еще достаточно молодой язык. Нужно, чтобы прошло время, технология устаканилась, язык был принят на вооружение сообществом и компаниями и завоевал свои ниши. Все-таки стек Typesafe еще слишком специфический и ограниченный по сравнению с тем же Spring. А все остальное в экосистеме пока жутко зеленое и нестабильное.
Я не совсем в курсе всех нюансов проекта, но вывод вполне определенный. Программеры приводят вполне аргументированные доводы как за, так и против новой технологии. Однако есть совершенно отличная точка зрения менеджера проекта, которая больше базируется на целесообразности использования той или иной технологии, которая в конечном итоге выражается в человекочасах, рисках и, соответственно, деньгах. С этой точки зрения люди приходят к совершенно иным выводам. Все потому, что менеджеры оценивают технологии с точки зрения эффективности решения конкретной задачи, тогда как программеры практически всегда в технологии видят неограниченные возможности, которые она им предоставляет. Поэтому «вау» вторых часто выливается в убыток для первых. И очень часто бывает так, что старая дубовая технология превосходит по надежности и минимизации затрат любую новую, которая казалось бы призвана сделать работу еще более эффективной. Любая инновация всегда рискована.
Злоупотребление абстракциями — любимое развлечение начинающих программистов, которые только познакомились с идеями ООП.
В данном контексте это не ООП, а модный ФП. Scalaz, shapeless и прочая академическая лабуда, превращает код в перлоподобную кашу, и никак не относится к решаемой задаче.
В итоге получилось так себе, но стоит ли винить во всем язык программирования?
Я и не виню ни в чем. Но статья именно про переход из Java в Scala, типа «Вы еще пишите на Java? Тогда мы идем к Вам.» Поэтому я пытаюсь задать правомерный вопрос: «а действительно ли стоит»? Новый язык, новый стек технологий (очень лимитированный и зеленый, по сравнению с Java), интеграция с Java очень условная, поддерживается такими компаниями как (кто?). Кроме того сам язык достаточно эстетически неприятный, неминималистичный, передроченый всевозможными концептами из разных парадигм (чувствуется жесткий методичный немецкий подход) Этакий монстр Франкенштейна-Одерски. Вобщем, на любителя. В своих проектах я по мере необходимости пользую Groovy, который тоже позволяет убрать под ковер многабукв. С нетерпением жду релиза Kotlin-а. Со Scala много раз не срасталось.
4. Воспоминания обоих изменятся, чтобы прийит к общему знаменателю. Либо будут существовать две пары наблюдателей: с воспоминаниями линии A и c воспоминаниями линии B.
Причина первая: опыт показывает, что назад не возвращаются
Вижу, что большинство находится под вау-эффектом, поэтому вброшу свою лопату пессимизма. У коллеги был реальный проект на scala. В команде было два скалиста и несколько джаверов. Задача — процессинг событий сети и интеграция с системами. Что было замечено (с позиции менеджера проекта):
Вопреки «высокому порогу вхождения», джависты достаточно быстро освоили основные принципы Scala и начали строчить код.
У скалистов не было единообразия в коде, стиле и решениях. Джависты же писали более читабельный и единообразный код, следуя гайдлайнам джавы.
Скалисты пытались использовать как можно больше возможностей языка, тогда как джависты ограничивались лишь необходимым минимумом.
Скалисты постоянно злоупоребляли абстракциями, которые не имели к предметной области никакого отношения.
Скалисты вцелом пытались написать короче (объявляя это «красотой» решения), тогда как джависты — понятней.
Интересный факт: скалисты не могли сходу с уверенностью сказать о том, что делает тот или иной фрагмент кода, написанного другим, из-за огромного количества неявностей, предоставляемых Scala. Только после анализа контекста с помощью IDE, а иногда просто в дебаггере.
Постоянно приходилось использовать решения из экосистемы Java, которые иногда давали проблемы с интеграцией в Scala (code-enhancement, reflection, etc.)
Отдельный вопрос — экосистема Scala. Извечная полемика какую библиотеку использовать, что подключать и вообще зачем новая библиотека scala, если есть прекрасная старая из java.
Хоть и сложно давать оценку производительности, но какого-либо существенного прироста замечено не было. Коллега уверен, что на java все было бы сделано быстрее и качественней.
Не аргумент, но головная боль для менеджера: специалистов по scala на порядок меньше, чем по java. Всегда будет проблема ресурсов.
В итоге, коллега уверен, что делать проект на scala было ошибкой и очень рискованным решением.
Это хорошо, если на ESB сидит интегратор, который планирует архитектуру, интерфейсы и интеграцию между системами. В проектах, в которых я работал, ты сам разрабатываешь интерфейс и отсылаешь свой WSDL команде ESB, которые коряво его проксят и расставляют глючные меппинги и потом упираются что-либо изменить. Заглушки для локальных тестов всегда делаем сами mock-ами — так надежнее, и не надо ждать пока ESB пошевелятся.
Я работал плотно со стеком IBM Websphere, поэтому у меня такое пессиместичное мнение. Сейчас клиент пользует OSB, а вся архитектура сервисов построена на SOAP. Но методологически ситуация не изменилась: команда ESB ничего не планирует, ни за что не отвечает, и играет роль такого ненужного звена в цепочке интергации. Плюс ко всему прочему зачастую плохо владеет продуктом. От любой проблемы отнекиваются: типа ошибки в ваших системах, плохо посылаете и разбирайтесь сами между собой.
Пример: клиент долго требовал от нас логгировать SOAP-месседжи, которыми мы обмениваемся со сторонними системами. На агрументы типа, что это 120% задача ESB, он говорил, что ему будет проще видеть все в наших логах, нежели каждый раз просить ESB достать месседж.
Хотелось бы знать, какова реальная необходимость в решении типа «прокси-сервис на Oracle Service Bus»? Все в поверпоинтах выглядит красиво, и картинка с архитектурой ESB тоже очень понятная и логичная. Клиент ненарадуется, что не зря потратил деньги.
В реале же к корпоративным сервисам добавляется тяжелый слой ввиде дорогого софта с командой разработчиков по его обслуживанию. Помимо того, что это вносит дополнительные проблемы с взаимодействием систем, ESB делает противоположную вещь для чего изначально предназначена: команда ESB должна знать все в деталях о всех интерфейсах всех систем всех используемых версий. Где же тут обещанный decoupling? В итоге если изменился интерфейс между двумя внутренними системами, приходится еще умолять команду ESB вставить изменения.
Тимлид — это такой человек, который знает абсолютно все о проекте, у которого можно спросить любую вещь и он ответит. Который имеет видение проекта как в целом, так и в деталях, обладает определенной интуицией в способе решения поставленных задач.
В любом успешном проекте есть такой человек, и не обязательно в IT: главный конструктор, ведущий инженер, etc… Если в проекте нет такого человека — это показатель обреченности проекта. Как бы мы ни старались развивать колаборационные навыки, идея и интуиция не масштабируются и не могут функционировать распределенно во многих головах сразу.
Элегантно решить не получится, т.к. кодогенерация — это костыль для языка. Различные фреймворки используют кодогенерацию для подмешивания в классы специфической функциональности. Яркий пример — JPA. EclipseLink умеет делать как статичную трансформацию во время компиляции (AST), так и динамическую трансформацию во время выполнения (Agent). Преимущественно должен использоваться второй способ, т.к. иначе генерируемый код является фреймворкозависимым и не может быть использован в другом приложении: например если я хочу сериализовать JPA-объекты и пересылать их клиенту, который знать не знает о JPA. То есть именно в зависимости от рантайма должны делаться те или иные преобразования.
Забейте на всё, что написано выше. Здесь есть проблема куда глубже.
А я считаю, что есть толк в массовом осознании того, что двое программистов могут вертеть многомиллиардную корпорацию. Наша работа сродни магии — ее плохо кто понимает, еще меньше владеют ей, но при этом все ей пользуются. При всем при этом мы — самая социально незащищенная группа: нет никаких способов бороться за свои права. Забастовка водителей автобусов прализует город. Забастовка мусорщиков — и весь город в грязи. Забастовка программистов или администраторов… кто-нибудь слышал что-либо глупее? Не выйти на работу врачу — это его право. А вот админу остановить сервер — это уже преступление. Во что это может вылиться? Скорей потребуют более жесткий контроль за деятельностью программеров.
В данном случае все легко закончится: программеры будут тупо все отрицать и говорить, что не ведали, что делают: типа нам сказали — мы сделали. Обвинитель, в данном случае компания, не сможет им ничего противопоставить: являясь одновременно и заказчиком, они не смогут утверждать, что программерам все было известно заранее, при этом не подставив себя.
Дырявая абстракция — это когда я описываю абстракцию «круглое и съедобное» и вынужден добавить в нее исключение «червивое» только для того, чтобы на основе него потом смочь описать яблоко. При всем при том, чтоб сливы, виноград, персики и т.д. червивыми не бывают. И тем не менее, поскольку все они наследуются от «круглого и съедобного», должны проверяться на червивость.
Помимо этого каждый из фруктов может иметь свое специфическое исключение, типа «незрелый», «гнилой» или «отравленный». Стандартный способ — описать абстрактное исключение «несъедобное», от которого наследуются «червивое», «гнилое», etc, и включить его в нашу абстракцию: «круглое съедобное» throws «несъедобное». Но если абстракция заведомо позиционируется как съедобная, зачем требовать каждого клиента нашей столовой тщательно осматривать фрукт перед съедением? Это будет только отпугивать публику. В случае же возникновения действительно исключительной ситуации, когда клиенту стало плохо, дело будут решать вышестоящие инстанции: врач, юрист или прокурор — в зависимости от тяжести ущерба.
Можно и так, но это не совсем одно и то же. У монады Try имеется тот же недостаток, что и у Option(al): она не ковариантна ко вложенному типу. В Java я легко могу написать:
class AbstractBuffer {
String read() throws IOException;
}
class MemBuffer extends AbstractBuffer {
@Override String read();
}
Для экземпляров MemBuffer компилятор не будет требовать обрабатывать IOException. С Try не будет такой возможности: если MemBuffer.read() будет возвращать Success, его все-равно придется дополнительно «разворачивать», чтобы получить String.
Кроме того, в одном блоке try-catch я могу оперировать сразу со многими вызовами «throws IOException», не заботясь о том, какой именно «вылетел». В случае же Try придется каждый вызов «разворачивать» отдельно со своим обработчиком.
Совершенно верно. Проверяемые исключения относятся к области контрактного программирования. При помощи оберток методы могут скрывать внутренние детали имплементации. В данном случае конфиг может читаться не только из файла, а из базы или запрашиваться с удаленного сервера. В этом случае SQLException, FileNotFoundException, IOException можно обернуть единым checked ConfigResourceException. Это все известно, хорошо и правильно.
А теперь реальные случаи, где действительно checked exceptions мешают и про которые автор не упомянул.
1. Закладка exception в интерфейсах.
Методы Input/OutputStream должны выбрасывать IOException. При этом в некоторых имплементациях интерфейса реальный эксепшн может вообще отсутствовать, как например в случае, если мы пишем в new DataOutputStream( new ByteArrayOutputStream())). Тем не менее компилятор здесь требует проверки.
В других же случаях эксепшн-причина сильно зависит от реализации ресурса (socket, file, network, etc...), но всегда обертывается в универсальный IOException, сильно затрудняя при этом ее детальный отлов на более высоком уровне (приходится смотреть ex.getCause()).
Другой пример — Java RMI, который для каждого remote-метода назойливо обязует прописывать throws RemoteException. Особенно достает, когда один и тот же интерфейс используется и для локальных, и для remote-вызовов.
2. Java API пронизано checked-эксепшнами, и нет никакого единообразия в их применении.
Например, задача парсинга:
new Integer(«123») кидает unchecked ParseException, также как и java.text.Format.parseObject(). Почему тогда мы так бережно должны заботиться о new URL(«www.my.com») и каждый раз оборачивать checked конструктор в MalFormedURLException?
3. Отвратительный дизайн ресурсов в Java. Именно для них, как утверждается, были первоначально введены checked exceptions, чтобы заставить программиста корректно закрывать ресурс.
Реально, во-первых, до try-with-resources не было нормальной формы отловить эксепшн и закрыть ресурс, и при этом ничего не потерять. Хотя все можно было бы исправить простым требованием, что в случае exception ресурс становится unusable и освобождается автоматически провайдером. Т.е. не нужно вызывать при этом close().
Во-вторых, большинство API, использующие ресурсы, выбрасывают generic checked exception, вроде java.sql.SQLException, совершенно не различая при этом, был ли это физический сбой ресурса (оборвался коннекшн, грохнулась база или диск), либо это ошибка в логике или транзакции (duplicate primary key, etc). Хотя обработка этих двух случаев кардинально отличается: в первом случае ресурс становится unusable, во втором — можно сделать откат и использовать дальше.
Вобщем, imho, checked exception хорош, когда метод должен возвратить выше что-то еще, кроме основного результата. И его использование сродни использованию Optional: который также явно декларирует, что метод, кроме основного результата может возвратить null, и что нужно позаботиться об этом.
новое ядро будет иметь производительность 40 тысяч сделок в секунду (сейчас — 20 тысяч)
Не зная деталей, цифра кажется достаточно смешной, с которой может справиться и мой ноут. Поэтому интересно узнать, какой примерный flow у одной транзакции: какие системы/модули задействуются, как устроено хранилище данных и логов, какие объемы данных, etc…
Ну да, как раз первый вариант. Основная ЦА — это религиозники и сомневающиеся. Первые поднимают бурление по поводу написанного и делают неплохую рекламу (Докинз — известный тролль в этом плане), вторые — будущие адепты учения о дарвинизме.
Поэтому бы не стал называть Докинза атеистом, ибо человек очень фанатичный и также слепо подвержен вере, пусть и вере в отсутствие Бога. Вместо того, чтобы тонко троллить религиозников, он суется в настоящую борьбу с ними, начинает что-то доказывать, включается в полемику, ссылается на неоднозначные аргументы типа дарвинизма, возводя их в степень догматов — т.е. демонструет все признаки приверженца кокурирующей религии. Многие видят его этаким рыцарем святого научного грааля, поэтому уважают и почитают. Те же, кто верят, считают антихристом. Но, надо отдать должное, свое дело он делает, популяризируя науку, и демонстрируя ущербность взгядов религиозников.
И, наконец, очень медленные. Чтобы посмотреть через что проходит ваш простой вызов к EJB, просто сделайте stacktrace…
Подключите фреймворк или библиотеку, которая наиболее подходит задаче. Альтернатив всегда десятки. На крайний случай, практически все, что входит в стек JEE доступно standalone.
Всегда задаю вопрос: а что такого особенного реализовано в JEE серверах? Какие супер-пупер технологии? Вебстек, альтернатив которому уже десятки? Наихудшая, непонятная и неудобная модель компоновки и запуска приложения, связанная с запаковкой всего в .Xar? Рудиментарный EJB? CDI? Webservices? JDBC pool? JPA? Все это доступно standalone без особого напряга. Правильный ответ дают лишь немногие: это JTA (distributed transactions). Если Вы не используете JMS и в проекте только одна база данных, можете смело забыть о JEE.
До сих пор всплывали промахи, связанные именно с сервером приложений и стеком JEE. Причем в этом случае архитектуру Вы уже сильно не поменяете.
Не успев полностью сесть на JEE вы уже прикручиваете сбоку какой-то левый велосипед, который и близко не лежал к стеку. Если уж Вы рекомендуете JEE, так используйте его средства: http servlets, JMS, Remote EJB, WS… Либо как белый человек пишите свой resource adapter, согласно спецификации. И уж там можете пользовать хоть java.nio, хоть netty…
Если Вы используете готовый, то нужно еще более внимательно расставить тайминги. Weblogic имеет более 100 настроек для пула. Еще надо найти и включить мониторинг для пула, чтобы время от времени выявлять незакрытые ресурсы и впоследствие ломать голову над тем, где в коде происходит leaking.
В JEE нет такого паттерна как «взаимодействие между потоками». Есть асинхронное выполнение, есть асинхронное взаимодействие посредством JMS. Все остальное синхронно.
JSP при использовании скриплетов (теги с процентиками) компилируется в .class и работает с той же скоростью, что и сервлет. Если вы используете различные tag libraries (например JSTL и EL), то перформанс будет немного проседать ввиду того, что приходится интерпретировать теги. Однако, вроде бы есть компилятор для JSTL. Если же вы используете JSF, то перформанс падает значительно. JSF — технология не для hiload.
Опять велосипед. Коммерческие сервера предлагают свои средства для сбора метрик и мониторинга. Это именно то, за что собирают деньги. А уж если мне нужно свой велосипед для мониторинга, то гораздо проще его будет присобачить без JEE.
Полная фигня. Сервер не отлавливает ничего. Сама архитектура JEE предполагает отсутствие дедлоков и правильную блокировку. Просто серверный пул конфигурируется и мониторится сервером. Плюс некоторые сервера могут корректно закрывать некоторые оставленные ресурсы типа connections из пулов. И еще корректно закрываться в случае остановки сервера. Недостаток всех пулов: нельзя использовать ThreadLocal (вернее очень осторожно).
С одной стороны это универсальный способ без лишних заморочек использовать различные сервис-провайдеры. Проблемы начинаются когда нужно сконфигурировать конкретный провайдер, ибо для этого не придумано хорошего стандартного способа. Часто это делается либо через system properties, либо через внешний файл конфигурации.
Теперь о Scala. Она изначально вообще задумывалась быть независимой от рантайма. Первые версии компилировались в JVM и .NET. Но по какой-то причине с .NET не сложилось — теперь это полудохлый независимый проект. Так что по меньшей мере некорректно говорить о Scala как продолжение Java, о чем собственно и заявляют создатели.
Какова же цель создания Scala? Со слов Одерски, он мечтал сделать единый универсальный гибкий и расширяемый язык (lingua franca) для всего, на котором можно было бы описывать предметные области и создавать собственные языки (DSL). За основу концепта была взята Java с примесью ФП и кучей сахара. Для семантического расширения языка предусмотрена мощная система типов, которая, в прочем, плохо ложится на ООП-core, в отличие от того же Haskell-а, в котором ООП не зашит в язык, а выводится искусственно. Ради расширяемой семантики язык загромоздили тоннами синтаксического сахара, implicit-ов и соглашений. Но вскоре поняли, что и этого недостаточно. Взляд создателей пал на Nemerle, который культурно предоставлял метапрограммирование через AST и макросы. Кому-то очень понравилась идея, а также душила жаба, что подобной фигни еще нет в scala. Поэтому вот вам: scala.meta, scala.macros.
Теперь о вашем вопросе: смысл Scala? Для истинных ценителей ФП есть красивейший Haskell. Как показывает практика, на скалу переходят именно искатели лучшей джавы, вопреки тому, что она для этого изначально не задумывалась. А для чего задумывалась? Сразу для всего в общем, и ни для чего в конкретике.
В данном контексте это не ООП, а модный ФП. Scalaz, shapeless и прочая академическая лабуда, превращает код в перлоподобную кашу, и никак не относится к решаемой задаче.
Я и не виню ни в чем. Но статья именно про переход из Java в Scala, типа «Вы еще пишите на Java? Тогда мы идем к Вам.» Поэтому я пытаюсь задать правомерный вопрос: «а действительно ли стоит»? Новый язык, новый стек технологий (очень лимитированный и зеленый, по сравнению с Java), интеграция с Java очень условная, поддерживается такими компаниями как (кто?). Кроме того сам язык достаточно эстетически неприятный, неминималистичный, передроченый всевозможными концептами из разных парадигм (чувствуется жесткий методичный немецкий подход) Этакий монстр Франкенштейна-Одерски. Вобщем, на любителя. В своих проектах я по мере необходимости пользую Groovy, который тоже позволяет убрать под ковер многабукв. С нетерпением жду релиза Kotlin-а. Со Scala много раз не срасталось.
В итоге, коллега уверен, что делать проект на scala было ошибкой и очень рискованным решением.
Я работал плотно со стеком IBM Websphere, поэтому у меня такое пессиместичное мнение. Сейчас клиент пользует OSB, а вся архитектура сервисов построена на SOAP. Но методологически ситуация не изменилась: команда ESB ничего не планирует, ни за что не отвечает, и играет роль такого ненужного звена в цепочке интергации. Плюс ко всему прочему зачастую плохо владеет продуктом. От любой проблемы отнекиваются: типа ошибки в ваших системах, плохо посылаете и разбирайтесь сами между собой.
Пример: клиент долго требовал от нас логгировать SOAP-месседжи, которыми мы обмениваемся со сторонними системами. На агрументы типа, что это 120% задача ESB, он говорил, что ему будет проще видеть все в наших логах, нежели каждый раз просить ESB достать месседж.
В реале же к корпоративным сервисам добавляется тяжелый слой ввиде дорогого софта с командой разработчиков по его обслуживанию. Помимо того, что это вносит дополнительные проблемы с взаимодействием систем, ESB делает противоположную вещь для чего изначально предназначена: команда ESB должна знать все в деталях о всех интерфейсах всех систем всех используемых версий. Где же тут обещанный decoupling? В итоге если изменился интерфейс между двумя внутренними системами, приходится еще умолять команду ESB вставить изменения.
В любом успешном проекте есть такой человек, и не обязательно в IT: главный конструктор, ведущий инженер, etc… Если в проекте нет такого человека — это показатель обреченности проекта. Как бы мы ни старались развивать колаборационные навыки, идея и интуиция не масштабируются и не могут функционировать распределенно во многих головах сразу.
А я считаю, что есть толк в массовом осознании того, что двое программистов могут вертеть многомиллиардную корпорацию. Наша работа сродни магии — ее плохо кто понимает, еще меньше владеют ей, но при этом все ей пользуются. При всем при этом мы — самая социально незащищенная группа: нет никаких способов бороться за свои права. Забастовка водителей автобусов прализует город. Забастовка мусорщиков — и весь город в грязи. Забастовка программистов или администраторов… кто-нибудь слышал что-либо глупее? Не выйти на работу врачу — это его право. А вот админу остановить сервер — это уже преступление. Во что это может вылиться? Скорей потребуют более жесткий контроль за деятельностью программеров.
В данном случае все легко закончится: программеры будут тупо все отрицать и говорить, что не ведали, что делают: типа нам сказали — мы сделали. Обвинитель, в данном случае компания, не сможет им ничего противопоставить: являясь одновременно и заказчиком, они не смогут утверждать, что программерам все было известно заранее, при этом не подставив себя.
Помимо этого каждый из фруктов может иметь свое специфическое исключение, типа «незрелый», «гнилой» или «отравленный». Стандартный способ — описать абстрактное исключение «несъедобное», от которого наследуются «червивое», «гнилое», etc, и включить его в нашу абстракцию: «круглое съедобное» throws «несъедобное». Но если абстракция заведомо позиционируется как съедобная, зачем требовать каждого клиента нашей столовой тщательно осматривать фрукт перед съедением? Это будет только отпугивать публику. В случае же возникновения действительно исключительной ситуации, когда клиенту стало плохо, дело будут решать вышестоящие инстанции: врач, юрист или прокурор — в зависимости от тяжести ущерба.
Для экземпляров MemBuffer компилятор не будет требовать обрабатывать IOException. С Try не будет такой возможности: если MemBuffer.read() будет возвращать Success, его все-равно придется дополнительно «разворачивать», чтобы получить String.
Кроме того, в одном блоке try-catch я могу оперировать сразу со многими вызовами «throws IOException», не заботясь о том, какой именно «вылетел». В случае же Try придется каждый вызов «разворачивать» отдельно со своим обработчиком.
А теперь реальные случаи, где действительно checked exceptions мешают и про которые автор не упомянул.
1. Закладка exception в интерфейсах.
Методы Input/OutputStream должны выбрасывать IOException. При этом в некоторых имплементациях интерфейса реальный эксепшн может вообще отсутствовать, как например в случае, если мы пишем в new DataOutputStream( new ByteArrayOutputStream())). Тем не менее компилятор здесь требует проверки.
В других же случаях эксепшн-причина сильно зависит от реализации ресурса (socket, file, network, etc...), но всегда обертывается в универсальный IOException, сильно затрудняя при этом ее детальный отлов на более высоком уровне (приходится смотреть ex.getCause()).
Другой пример — Java RMI, который для каждого remote-метода назойливо обязует прописывать throws RemoteException. Особенно достает, когда один и тот же интерфейс используется и для локальных, и для remote-вызовов.
2. Java API пронизано checked-эксепшнами, и нет никакого единообразия в их применении.
Например, задача парсинга:
new Integer(«123») кидает unchecked ParseException, также как и java.text.Format.parseObject(). Почему тогда мы так бережно должны заботиться о new URL(«www.my.com») и каждый раз оборачивать checked конструктор в MalFormedURLException?
3. Отвратительный дизайн ресурсов в Java. Именно для них, как утверждается, были первоначально введены checked exceptions, чтобы заставить программиста корректно закрывать ресурс.
Реально, во-первых, до try-with-resources не было нормальной формы отловить эксепшн и закрыть ресурс, и при этом ничего не потерять. Хотя все можно было бы исправить простым требованием, что в случае exception ресурс становится unusable и освобождается автоматически провайдером. Т.е. не нужно вызывать при этом close().
Во-вторых, большинство API, использующие ресурсы, выбрасывают generic checked exception, вроде java.sql.SQLException, совершенно не различая при этом, был ли это физический сбой ресурса (оборвался коннекшн, грохнулась база или диск), либо это ошибка в логике или транзакции (duplicate primary key, etc). Хотя обработка этих двух случаев кардинально отличается: в первом случае ресурс становится unusable, во втором — можно сделать откат и использовать дальше.
Вобщем, imho, checked exception хорош, когда метод должен возвратить выше что-то еще, кроме основного результата. И его использование сродни использованию Optional: который также явно декларирует, что метод, кроме основного результата может возвратить null, и что нужно позаботиться об этом.
Не зная деталей, цифра кажется достаточно смешной, с которой может справиться и мой ноут. Поэтому интересно узнать, какой примерный flow у одной транзакции: какие системы/модули задействуются, как устроено хранилище данных и логов, какие объемы данных, etc…
Поэтому бы не стал называть Докинза атеистом, ибо человек очень фанатичный и также слепо подвержен вере, пусть и вере в отсутствие Бога. Вместо того, чтобы тонко троллить религиозников, он суется в настоящую борьбу с ними, начинает что-то доказывать, включается в полемику, ссылается на неоднозначные аргументы типа дарвинизма, возводя их в степень догматов — т.е. демонструет все признаки приверженца кокурирующей религии. Многие видят его этаким рыцарем святого научного грааля, поэтому уважают и почитают. Те же, кто верят, считают антихристом. Но, надо отдать должное, свое дело он делает, популяризируя науку, и демонстрируя ущербность взгядов религиозников.
Критики MUMPS прямо называют эту технологию устаревшей[3] и указывают на такие недостатки MUMPS как[3][4]:
Язык MUMPS критики называют провоцирующим ошибки, поскольку[3][4]: