Автор: vit

  • HTTPS авторизация по сертификату

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

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

    Более распространен такой способ авторизации не в клиент-серверных решениях, а скорее в межсерверном взаимодействии. Например при решения задач в сфере B2B, когда необходимо отправлять запросы к различным серверам контрагентов и внешним системам. Отчасти это связанно с тем, что одним из популярных способов создания таких коммуникаций является использование веб-служб, что в свою очередь означает программную отправку HTTP запросов. Поскольку внутренняя реализации JAX-WS, базируется на использовании стандартных классов (URL, HttpURLConnection и т.д.), решив задачу в общем виде (отправка https запросов с авторизацией по сертификату) автоматически решается задача для клиента веб-службы (речь идет о JAX-WS, в Axis2 задачу решать можно немного другим способом).

    Самое простое что можно сделать для решения этой задачи — указать ключи и пароли в системных свойствах:

    -Djavax.net.ssl.keyStore=privateKey.jks
    -Djavax.net.ssl.keyStorePassword=myPrivateKeyPassword
    -Djavax.net.ssl.trustStore=truststore.jks
    -Djavax.net.ssl.trustStorePassword=myTrustStorePassword
    

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

    Хранилище ключей может иметь тип не только JKS (Java Key Store), но например быть в более распространенном формате PKCS12. В таком случае в настройках следует указать тип хранилища:

    -Djavax.net.ssl.keyStoreType=pkcs12
    -Djavax.net.ssl.keyStore=privateKey.p12                
    -Djavax.net.ssl.keyStorePassword=myPrivateKeyPassword
    

    Очень хорошо описаны отличия в использовании JKS и PKCS12 в статье Java 2-way TLS/SSL (Client Certificates) and PKCS12 vs JKS KeyStores.

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

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

    Общая последовательность шагов будет выглядеть следующим образом.
    1. Получить хранилище ключей.
    2. Создать объект класса менеджера ключей.
    3. Создать объект управляющий доверенными сертификатами.
    4. Произвести инициализацию ssl-контекста.

    Теперь нужно разобраться, кто это такой “менеджер ключей” и “управляющий доверенными сертификатами”, а также с кем еще возможно придется столкнуться. Для этого приведу сильно упрощенную диаграмму классов:
    sslcontext

    Из диаграммы легко видеть как можно управлять поведением работы программы. Например, чтобы поменять логику выбора алиаса, можно сделать наследника класса менеджера ключей (KeyManager).
    Для этого вначале нужно получить хранилище ключей (KeyStore), а дальше сделав своего наследника, который будет работать с ключами, передать его в метод для инициализации SSL контекста. Самый простой способ сделать такого наследника — получить менеджера ключей по-умолчанию, а затем обернуть его методы таким образом, чтобы основные методы “проксировались” и в то же время можно было перекрыть нужный метод со специфической логикой (выбор алиас, отслеживание какой ключ/принципал используется и тд).

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

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

    
    /**
     *
     * @author Vit vit@programmisty.com
     */
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            SSLContext sc = SSLContext.getInstance("SSL");
    
            // Каким-то образом получили хранилище ключей. Это за рамками статьи.
            KeyStore keystore = ... ;
    
            String algorithm = KeyManagerFactory.getDefaultAlgorithm();
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
            // не забываем инициализировать менеджера ключей
            keyManagerFactory.init(keystore, password);
            // получаем список менеджером (при необходимости делаем наследника и/или оборачиваем keyManager)
            KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
            // если у нас свой список доверенных серверов
            TrustManager[] trustManagers = getTrustManagers("/trusted.jks", "trustedPassword".toCharArray());
            sc.init(keyManagers, trustManagers, null);
            // проставляем контекст
            SSLContext.setDefault(sc);
            // для проверки отправляем запрос
            String url = "https://my-secure-server.com";
            try (InputStream in = new URL(url).openStream()){
                System.out.println(IOUtils.toString(in));
            }
        }
    
        /**
         * если у нас какой-то свой файлик с доверенными сертификатами
         */
        private static TrustManager[] getTrustManagers(String path, char[] passwd) throws Exception {
            String algorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
            // Загружаем доверенных
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            // Из ресурсов, так проще. 
            InputStream keystoreStream = Demo.class.getResourceAsStream(path);
            keystore.load(keystoreStream, passwd);
            trustManagerFactory.init(keystore);
            // 
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            return trustManagers;
        }
    }
    
    
  • Заметки по Derby DB

    Нельзя сказать, что к Derby DB у меня особо теплые отношения. Первое знакомство с ней произошло много лет назад, когда на работе возникла идея прикрутить Derby вместо полноценной базы данных, чтобы проще было готовить демку программы к выставке. Идея была в том, что если взять легковесную встраиваемую базу, то тогда развертывание демонстрационного дистрибутива сильно упростится — скопировал файлики и ничего настраивать не нужно (в отличие от Оракла). В случае если нам нужен всего-лишь выставочный демонстрационный образец ПО такое решение было вполне оправдано. Почему выбор пал в тот момент именно на дерби думаю сейчас мало уже кто вспомнит.
    В итоге конечно всё прикрутить получилось, но скорость работы базы на тот момент оставляла желать лучшего. Возможно где-то я был не прав (был молодым и неопытным), а возможно и сама база была “юной” и не достаточно расторопной. derby_db_logo

    С тех пор прошло много времени, Derby уже давно поставляется вместе с JDK под именем Java DB, поэтому думаю в жизни многих Java-программистов также возникали случаи совместной работы с этой удивительной базой данных. Собственно поэтому решил описать некоторые её капризы и особенности. Сразу хочу заметить, что эту БД использую в жизни не так часто и возможно именно поэтому ее поведение меня иногда удивляет.

    1.Кидается исключениями при отключении.

    Чтобы отключить БД в embedded режиме, нужно в JDBC-URL прописать “jdbc:derby:;shutdown=true”. Если всё нормально, в вас обязательно при отключении кинут исключением SQLException с кодом XJ015. К этому нужно привыкнуть и не пугаться.

    2.Режим использования RAM (In-memory).

    У Derby есть не плохой экспериментальный режим, когда она работает в памяти.
    Удобно использовать для создания временного окружения (чтобы не удалять созданные файлы и директории) или в различных jUnit-тестах.
    Опять таки все делается через URL, например для создания пишем: “jdbc:derby:memory:myDB;create=true”.

    При этом если вы сделаете shutdown, но не потушите JVM, то ваша БД не почистится. Чтобы удалить данные из памяти нужно сделать сделать drop (jdbc:derby:memory:myDB;drop=true), который сам сделает shutdown:
    You can shut down an in-memory database using the shutdown=true attribute before you drop the database, but this is optional. Dropping the database also performs the shutdown.

    3.JRE7u51

    В JRE7u51 поменялись ограничение в настройках безопасности. Поэтому при запуске дерби в сетевом режиме могут валиться исключения AccessControlException.
    На официальной странице oracle предлагается решение, в котором необходимо настроить собственный security.policy файл, чтобы в нем был доступ к порту (по-умолчанию 1527). Например так:

    grant {
        permission java.net.SocketPermission "localhost:1527", "listen";
    };
    

    Хорошая пошаговая инструкция на странице администрирования.

  • Распараллеливание задач в Java через InvokeAll

    Одно время у меня были некоторые сомнения имеет ли смысл публиковать эту статью, т.к. в целом мне нечего сказать такого, что нельзя было найти в официальной документации об invokeAll. Затем, при общении с другими программистами, стал время от времени замечать не совсем правильное (на мой взгляд) понимание его работы. Поэтому пока есть свободное время решил все-таки закончить эту заметку.

    Сразу хочу заметить, что мне не очень хочется углубляться в описание всей мощи java concurrent API, а просто расставить некоторые акценты при работе над небольшой простой задачей. Она может возникнуть в жизни каждого программиста, он замечает некоторые независимые операции и у него появляется нестерпимое желание их распределить по нескольким потокам. Грубо говоря, у вас есть какой-то метод, который можно было бы безболезненно запихнуть в Runnable-ы, стартануть и подождать когда все закончат свою работу.

    Понятно, что для этого может подойти invokeAll т.к. в описании про него явно сказано: “Executes the given tasks, returning a list of Futures holding their status and results when all complete.”

    Так вот, некоторые программисты не дочитывают последние слова и думают, что нужно самому контролировать процесс, ждать и “жать на тормоз”, проверять все ли потоки завершились, периодически дергать в цикле future.get(), join-ить или делать другие различные телодвижения. Конечно так поступают не все, но тем не менее такое бывает. Для того, чтобы разобраться в том, что происходит на самом деле, достаточно взглянуть в базовую реализацию этого метода (AbstractExecutorService.java). Надо же пользоваться тем, что src.zip в JDK все еще продолжают подкладывать: (далее…)

  • DCE VM + HotSwap

    Горячая замена.

    Исходной предпосылкой было как-то упростить процесс разработки/отладки. В некоторых ситуациях, например когда запуск-перезапуск приложения или теста занимает продолжительное время, очень удобно пользоваться возможностью подправить логику работы уже запущенной программы.
    В поисках решения наткнулся на довольно занятное решение – Dynamic Code Evolution VM. Данная виртуальная машина является результатом работ проведенных в рамках исследовательского проекта Институтом системного программного обеспечения им. Иоганна Кеплера в г. Линце (Австрия).

    Если грубо описать полученный результат – это специальная “пропатченная” Java VM, которая позволяет на лету править классы в работающей машине. Главная плюшка – если обычно при дебаге вы можете “на горячую” менять содержимое метода, то в DCE VM можно еще и добавлять/удалять методы и поля в классе.

    К сожалению с установкой DCE VM у меня не заладилось с самого начала. Инсталлятор не сработал, в итоге пришлось просидеть полночи в попытках заполучить эту чудную VM. К решению этой задачи пробовал подступиться с разных сторон. Пытался собрать исходники. Собирать пришлось из под cygwin-а (в очередной раз пожалел, что сейчас у меня рабочая операционка не Linux). Потом возникли сложности с установкой “Microsoft SDKs Windows v7.1”, который почему-то не хотел устанавливаться. В итоге, правдам и неправдами, перед самым рассветом, перерыв кучу ссылок в интернете различными кривыми путями мне удалось стать счастливым обладателям этой машинки. Конечно сейчас, оглядываясь назад, у меня создается впечатление, что на самом деле я сделал кучу лишних шагов и про установку DCE VM информации более чем достаточно, главное внимательно читать инструкцию.

    Мои эксперименты.

    После того как всё настроил Hot Swap заработал сразу на:

    • Простых Java SE проектах.
    • Java Web проектах под Apache Tomcat.

    Схема работы простая. Запускаем под дебагом → Делаем изменения → Жмем Apply Changes.

    apply_code_changes

    Если речь идёт о более экзотических случаях, например разработка Rich приложений на Netbeans Platform – то горячая замена у меня не заработала. Чуть позже у меня появилась гипотеза, что возможно это связано с тем, что у Netbeans Platform свой ClassLoader. Возможно гипотеза неверна и дело в настройках, думаю в свободное время посмотреть более внимательно исходники проекта и утилит, которые идут вместе с ним. (далее…)

  • Java и парсинг XML

    Тема сегодняшней статьи будет касаться XML поскольку сегодня (10 февраля) XML-ю исполнилось 16 лет!
    XML и Java дружат очень давно и в интернете можно найти множество учебных материалов посвященных парсингу XML-файлов, но не смотря на это, время от времени встречаю в коде разных программистов некоторые не совсем удачные решения при разборе XML.
    Эта статья возможно не будет интересна тем, кто занимается подобными задачами из года в год и парсит XML-ки с закрытами глазами, но возможно для тех кто только начал вникать в задачу, эти пару прописных истин будут полезны.

    Итак.

    1. Поиск нужных элементов.

    Метод Element.getElementsByTagName возвращает список всех подэлементов с указаным именем.

    Всех значит прямо всех, не только непосредственных “детей” этого элементов, но и “внуков” (детей их детей) и “правнуков” и т.д.
    Другими словами, если у нас есть следующий XML: (далее…)

  • Умножаем на пи (π = 3,14159265…)

    Около месяца назад мне попался на глаза шедевральный пост, в котором приводится гениальное по простоте, остроумное и изящное математическое доказательство теории: “при оценки сроков и объема работы над проектом желательно умножать исходную оценку на Пи”. Оригинальный труд находится по следующей ссылке: http://www.altdevblogaday.com/2013/11/15/always-multiply-estimates-by-pi/. В этой статье хотел изложить краткий пересказ доказательства.

    Допустим у вас есть какой-то исходный план действий.
    Обозначим его вектором направленным из точки A в предполагаемую точку B0.
    blog-1

    Времена меняются. Цель из точки B0 отодвигается под фактором различных обстоятельств в точку B.
    blog-2

    Естественно не бывает так, что всё идет гладко, возникают трудности, которые приводят к отклонению от прямой. В итоге путь, по которому вы прибываете к цели является кривой.
    blog-3
    (далее…)

  • Java и десктоп приложения. Впечатления от Netbeans Platform.

    Последнее время проектирую и разрабатываю десктоп приложение на Java. После нескольких лет разработки веб/мобильных решений было очень интересно вернуться к десктопу. Сейчас, в эпоху расцвета различных веб-фреймворков (только среди Java: Spring MVC, GWT, JSF, Tapestry, Wicket, Vaadin и т.д.), для разработки десктопных приложений на Java не такой уж большой выбор.
    На мой взгляд, на данный момент есть всего три более-менее популярных подхода:

    0. Чистый Swing/JavaFX
    1. Использовать Eclipse RCP (Rich Client Platform)
    2. Netbeans Platform

    Поскольку с самого начало было понятно, что предстоит разработать сложную систему с несколько десятков различных формочек, множеством сложных таблиц с группировкой/сортировкой данных, а в перспективе графики, схемы и другие компоненты, то естественно у меня не было желание использовать чистый Swing/JavaFX, а воспользоваться какой-нибудь из платформ.

    Первым делом были мысли использовать все-таки Eclipse (в прошлом у меня был опыт работы с ним). Конечно впечатления были не самые лучшие, но прошло больше 8 лет с тех пор как я имел с ним дело и многое могло измениться. Просмотрел изменения и одновременно начал опрашивать друзей, писал ли кто-нибудь в последнее время для Eclipse RCP. В итоге про Eclipse я услышал мало хорошего. Если резюмировать, главный вывод, который можно было сделать после бесед с друзьями — Eclipse RCP использовать можно, но скажем деликатно, без особого удовольствия. В конечном счете я решил переключиться на Netbeans, к которому присматривался уже давно.
    Забегая вперед скажу, что в целом мне платформа пока нравится. (далее…)

  • Duke, Coworking, Widget.

    За последнее время прошло несколько важных событий, о которых давно хотел написать.
    Про одну новость я уже просто не имею права писать с ещё большей задержкой и опозданием…
    Итак, во-первых, самое главное событие о котором я узнал в сентябре — команда российских программистов получила Duke Award 2013 в Сан-Франциско!
    DukeAward2013
    Ребята занимаются разработкой симулятора для Java Card Runtime Environment (jCardSim), пишут обфускатор и ПО для защиты Андроид приложений от реверса, а также ведут различные, по-настоящему сложные, Java-разработки. Другими словами занимаются не какими-то поделками вроде корпоративного веб-софта, клепание порталов и другими типовыми B2B/E-Commerce/Banking/Enterprise проектами, а работают над фундаментальными разработками и действительно непростыми вещами, в отличие от многих-многих Java программистов Москвы.

    Друзья, еще раз мои поздравления!

    Во-вторых, мы пытаемся возобновить наши встречи программистов или как сейчас модно говорить MeetUp-ы. Конечно сейчас уже будет не Scala, основы языка мы разобрали давным давно, у некоторых из нас использование Scala стало вполне будничным и хочется чего-то нового. Следующие встречи предполагаем посвятить процессингу, Arduino, малинке (raspberry pi). Всей нашей небольшой группе захотелось двинуться в сторону железок и интерактив арт. Думаю как всегда половина времени уйдет на общение с железками/компьютерами, а половина на распитие кофе и общение на общие темы.
    Место встречи — на территории дизайн-завода Флакон или в кофейнях (как старые добрые времена).

    В связи с этим еще одна небольшая новость. Сейчас обитаю в коворкинге StartHub-а, я о нем еще не рассказывал, он находится также во Флаконе, но немного в глубине территории, напротив летнего бассейна. Он расположен не так далеко от предыдущего коворкинга, в котором я арендовал себе рабочее место в прошлом году.
    Для любопытствующих выкладываю фото комнаты где я сижу и ссылку на сам коворкинг.

    Наконец последняя новость. Мы недавно с друзьями решили вместе сделать Halloween Widget для Android. Как всегда всё в последний момент, но мне кажется получилось намного круче чем я ожидал.
    По сути это тот же робот, только сильно доработанный. Из функциональных вещей добавился фонарик (Бека – спасибо, за пример кода!). Включается нажатием на центральную кнопку. Поскольку фонарик по-сути использует вспышку от встроенной фотокамеры, то для работы потребуется разрешение для работы с камерой: android.permission.CAMERA.

    Огромный респект нашему дизайнеру Грише за проделанную работу и Тане, за львиную доли работы по переделке-улучшению UI/UX!
    Выкладываю пару картинок, сам виджет можно скачать с маркета и при желании по тестировать.


    unnamed unnamed2

  • Сколько стоит?

    Так получилось, что я знаком со многими программистами, которые работают в крупных (и не очень) софтверных компаниях в качестве наемных сотрудников, т.е. на окладе. На сегодняшний день Москве можно наблюдать два явления:
    1. Дефицит квалифицированных кадров.
    2. Кризис самореализации. Много ИТ специалистов в прошлом учились в лучших высших учебных заведениях России, но текущая их работы не в полной мере позволяет им реализовать свой потенциал. Одни мирятся с таким положением дел, у других возникает желание “изменить судьбу”, открыть свое дело, начать стартап, освободиться от “офисного рабства”.

    Как следствие они начинают карьеру молодого предпринимателя, пытаясь начать самостоятельные проекты, искать заказы на разработку ПО. При этом у многих сохраняются наивные представления о том, как продавать свои услуги, на каких условиях работать с клиентом и самый главный вопрос возникающий у начинающего московского программиста-предприниматели – сколько стоят его услуги по созданию программного обеспечения. Для многих технически подкованных специалистов моего возраста в школьные годы не составляла особого труда решить примера вида:
    blog_primer

    Пример из сборника задач Сканави М.И. для поступающих ВТУЗы. В прошлом, те кто хотел поступить в ВУЗ могли решить такой пример не особо себя утруждаю, как мы шутили «спинным мозгом». Наверное сейчас с появлением ЕГЭ эпоха задач из Сканави уходит в прошлое.

    С другой стороны, когда нужно сделать не намного более сложные арифметические и алгебраические операции, но вместо конкретных чисел будут стоять налоги, накладные расходы, человеко-часы, риски, объемы, сроки, скидки и другие составляющие, то это вызывает панику. Человек с высшим техническим образованием может потратить несколько дней или даже недель, чтобы найти грубые ошибок в своих вычислениях.
    Другими словами, если речь идёт о готовом математическом выражении — всё просто, но если это якобы “бизнес” ситуация и нужно ответить на вопрос “за 100 000 сделаешь программу?” или “сколько будет стоит сделать мобильное приложение?”, то начинается тупёж. Например постоянно сталкиваюсь с людьми, которые путаются с процентами и не могут посчитать какую цену они должны указать заказчику, чтобы у них осталось 100 000 рублей после оплаты налога в 6% с дохода?
    Казалось бы ответ очевиден – приблизительно 106 383 рубля, но даже в таком простом примере многие делают ошибки (считают 106 000) или вообще не учитывают налог в конечной стоимости («да ладно, пусть, чего мелочится, всего 6%»). Когда же нужно проделать более «сложные» вычисления, т.е. учесть в цене все затраты (часы на согласование проекта, тестирование, внедрение, отчисления в фонды, обслуживание счета в банке, расходы на аренду, обрудывание и другие расходы), то в итоге некоторые делают множество существенных арифметических, алгебраических и алгоритмических ошибок. Хотя на самом деле, здесь нет ничего сложного.

    Ошибка 1.

    Допустим существует некий абстрактный московский java-программист. Его зарплата 120 000 в месяц. Он решил, что начинает работать на себя. Какую стоимость человеко-часа выставлять заказчику? Берем зарплату и делим на среднее количество рабочих часов в месяц (допустим 164,17 часов). Получаем стоимость часа около 731 рубля.

    Давайте приведем аналогию из сферы услуг. Я знаю фитнес-центр в котором годовой абонемент стоит 16 000 рублей. Это недорого для Москвы (даже скажем средний, бюджетный вариант). Фитнес открыт ежедневно, работает по 12 часов в день. Разделим 16 000 на количество часов в году (365 дней * 12 часов = 4 380 часов) и получим стоимость часа равную 3 рубля 65 копеек. Посчитав это, я решаю пойти и позаниматься 2 часа, т.к. по моим расчетам должен заплатить 7 руб 30 копеек. Вопрос, почему администрации фитнес-центра требует с меня за разовое посещение 500 руб?! Что за наглость?

      2 * (16 000 / (365 * 12)) = 7.30 != 500

    Устраиваясь на работу, программист предоставляет свои услуги работодателю не на один месяц, а как правило по бессрочному договору, т.е. работать будет годами (хотя на обычно специалист меняет работодателя через 2-5 лет). Вы как бы “продаете” годовой абонемент своему работодателю — будут для вас задачи или нет, это уже не ваши проблемы. Фитнес-центр же не виноват, что кому-то лень тащить свое тело в зал и кто-то не приходит заниматься уже вторую неделю. Так и здесь, работодатель сам должен обеспечить вам фронт работы, а вы качественно программировать и получать каждый месяц зарплату. Если задач нет, то можно плевать в потолок или гонять танки, вашей вины в простое нет.
    Другими словами, если вам предлагают проект на условиях: 2 миллиона рублей на 12 человеко-месяцев, деньги поступают каждый месяц, заказчик покупает вам необходимую для работы компьютерную технику, оплачивает интернет и аренду рабочего места, то можно говорить о том, что стоимость часа равна 731 рублей. Если это подработка на 60-100 часов, то о каких 731 рублей за час может идти речь? Вас же за 7 рублей в фитнес-клуб никто не пустит, хотя стоимость часа рассчитана по схожему принципу. Думаю для любого торговца на улице очевидна причина в разнице цены за килограмм картошки между покупкой ее вагонами и трех килограммов в розницу, но почему-то у программистов-предпринимателей работает “линейное” мышление в расчете цены.

    Ошибка 2.


    Есть такой бородатый анекдот:
    Новый русский открыл фотосалон и дал объявление: “Приглашаю фотомодель для съемки. Оплата наличкой на месте. За час работы 20 тысяч баксов”.
    Набежала куча моделей, отобрали одну, снимали с вечера и до ночи.
    Приходит новый русский:
    – Ну что, фотограф, сколько наснимал?
    – Четыреста кадров.
    – А выдержку ставил какую?
    – 1/200 секунды.
    – Ну ты, девка, в натуре, на две секунды всего лишь наработала, держи 12 баксов.

    К чему я вспомнил этот старый анекдот из прошедшей эпохи? (далее…)

  • Apples and oranges. Сравнение веб-фреймворков.

    Этим летом ко мне обратился старый знакомый, который хотел начать разработку нового веб-проекта. Он хотел пообщаться/посоветоваться на тему современных инструментов (фреймворков) для разработки веб-приложений. Дело в том, что у него скорее планировалась не разработка нового, а переделка старого проекта, сделанного на JSP и сервлетах, базовая архитектура которого ваялась еще в начале 2000-ных. В прошлом я немного участвовал в жизни этого программного продукта (доработки по Hibernate, прикручивал apache fop и т.д.), поэтому был немного в курсе внутренних особенностей системы.

    В целом это было добротное веб-приложение на Spring-e и оракловой СУБД. Думаю многие из нас в былые времена делали подобные вещи. С тех пор многое поменялось, одни инструменты сильно развились, появились абсолютно новые, а некоторые безнадежно устарели и канули в Лету. В итоге мы решили встретиться, пообщаться, попить кофе и обсудить, кто с чем столкнулся на профессиональном поприще за последние несколько лет, а также поделиться впечатлениями об использовании тех или иных инструментов.
    На мой взгляд к 2013 году человечество создало такое огромное количество библиотек, утилит, платформ и других полезных и бесполезных вещей для создания веб-приложения, что разобраться в них становится все сложнее и сложнее. Суть проблемы заключается в том, что обилие различных модных слов создают кашу в голове программистов.

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

    Ведь на самом деле, многие инструменты качественно отличаются друг от друга и сравнивать их порой не представляется возможным. Apple_and_Orange_-_they_do_not_compareВ английском языке существует выражение “сравнивать яблоки и апельсины“, в русском языке ближайшим аналогом этого высказывания “путать теплое с мягким“. Сравнивать разные по сути вещи. Например, все равно что сравнивать JSF и jQuery.

    Поэтому, чтобы внести ясность, я решил раскидать “яблоки к яблокам, а апельсины к апельсинам”. В итоге получился следующий текст.
    (далее…)