Показаны сообщения с ярлыком java. Показать все сообщения
Показаны сообщения с ярлыком java. Показать все сообщения

четверг, 24 февраля 2011 г.

Effective Testing

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

четверг, 24 июня 2010 г.

The Craftsman

Читая очередную книгу за авторством Роберта Мартина (a.k.a. Uncle Bob), нашел адрес его сайта. Там тоже есть очень много полезного. В особенности рекомендую его цикл статей "The Craftsman". Ничего лучше по TDD in Action я еще пока не встречал - тут тебе и клиент-серверные приложения, и многопоточность, и еще куча всего. Ну и написано довольно смешно и легко читается. Скорее это можно даже назвать не циклом статей, а сборником рассказов про некоего молодого программиста где-то в далекой галактике))

вторник, 22 июня 2010 г.

Joda Time

В общем-то реализация работы с временем и датами в Java неудобна и это давно всем известно. Как хорошую замену дефолтному API можно использовать Joda Time:

Joda-Time has been created to radically change date and time handling in Java. The JDK classes Date and Calendar are very badly designed, have had numerous bugs and have odd performance effects. Here are some of our reasons for developing and using Joda-Time:
  • Easy to Use. Calendar makes accessing 'normal' dates difficult, due to the lack of simple methods. Joda-Time has straightforward field accessors such as getYear() or getDayOfWeek().
  • Easy to Extend. The JDK supports multiple calendar systems via subclasses of Calendar. This is clunky, and in practice it is very difficult to write another calendar system. Joda-Time supports multiple calendar systems via a pluggable system based on the Chronology class.
  • Comprehensive Feature Set. The library is intended to provide all the functionality that is required for date-time calculations. It already provides out-of-the-box features, such as support for oddball date formats, which are difficult to replicate with the JDK.
  • Up-to-date Time Zone calculations. The time zone implementation is based on the public tz database, which is updated several times a year. New Joda-Time releases incorporate all changes made to this database. Should the changes be needed earlier, manually updating the zone data is easy.
  • Calendar support. The library currently provides 8 calendar systems. More will be added in the future.
  • Easy interoperability. The library internally uses a millisecond instant which is identical to the JDK and similar to other common time representations. This makes interoperability easy, and Joda-Time comes with out-of-the-box JDK interoperability.
  • Better Performance Characteristics. Calendar has strange performance characteristics as it recalculates fields at unexpected moments. Joda-Time does only the minimal calculation for the field that is being accessed.
  • Good Test Coverage. Joda-Time has a comprehensive set of developer tests, providing assurance of the library's quality.
  • Complete Documentation. There is a full User Guide which provides an overview and covers common usage scenarios. The javadoc is extremely detailed and covers the rest of the API.
  • Maturity. The library has been under active development since 2002. Although it continues to be improved with the addition of new features and bug-fixes, it is a mature and reliable code base. A number of related projectsare now available.
  • Open Source. Joda-Time is licenced under the business friendly Apache License Version 2.0.

пятница, 11 июня 2010 г.

Scala rocks again

В отличие от Java, Scala позволяет наследоваться от Enumeration. Что упрощает дело в некоторых случаях. Плюс еще есть case classes, что даёт еще больше простора для маневров.. Чувствую, то, что я уже второй день пытаюсь красиво сделать на Java, на Scala выйдет быстро и элегантно.

пятница, 12 марта 2010 г.

Что-то последнее время в Киеве ощущается нехватка leading java specialists. Получил аж три предложения за несколько дней на разные проекты на ведущие позиции. Неужели в кризис студентов больше решили не набирать пачками? ))

четверг, 25 февраля 2010 г.

Еще о Scala

Краткость - сестра таланта. А программист - ленивое существо :) За что мне понравилась Scala - так это за краткость. Вот если посмотреть на примере - надо посчитать норму вектора. Для тех, кто уже забыл, что это такое - корень из суммы квадратов всех его координат. Пускай вектор у нас представлен списком, каждый элемент которого - соответствующая координата. Ниже 2 реализации - на Java и на Scala:

Java

List<Double> vector = new ArrayList<Double>();
vector.add(-1.0);
vector.add(2.0);
vector.add(3.0);
Double norm = 0.0;
for (Double coord : vector) {
norm+=coord*coord;
}

norm = Math.pow(norm, 0.5);

Scala

val v = -1.0::2.0::3.0::Nil
val norm = Math.sqrt(
(0.0 /: v)((x, y) => x + y * y))

Разница в обьёмах набранных буков очевидна :) А результат один - корень из 14.

среда, 4 ноября 2009 г.

Google Guice – вопрос к джавистам

Будет ли интересна заметка по разбору этого фреймворка, с примерами? Недавно его как следует поковырял, если будет кому-нибудь интересно, напишу про него.

воскресенье, 1 ноября 2009 г.

Хороший web фреймворк

На профильном блоге заметка о простом в использовании, но эффективном веб-фреймворке, написанном на pure Java.

четверг, 29 октября 2009 г.

Mathematica+Java

В студенческие годы сильно мне помогал математический пакет Mathematica от Wolfram Research, всякие там задачи по моделированию и оптимизации считать. Единственно чего не хватало - так это возможности его интегрировать в свои программы. Уж очень помогло бы при написании курсовых. На днях обнаружил, что у него такая возможность таки есть, не мог не попробовать, хоть мне это уже особо и не надо сейчас. Ну может кому пригодится. Про это в профильном блоге.

среда, 3 июня 2009 г.

Java-дайджест

Небольшая подборка вкусного по java-related направлению, ибо на нормальные статьи нет времени катастрофически. Итак..

Smooks: фреймворк для трансформации данных. Умеет преобразовывать XML to XML, CSV to XML, EDI to XML, XML to EDI, XML to CSV, Java to XML, Java to EDI, Java to CSV, Java to Java, XML to Java, EDI to Java etc.
http://www.smooks.org

GridGain: фреймворк для адаптации своих программ к распределенным вычислениям, а.к.а Cloud Computing. Среди прочего, позволяет разрабатывать выполнять юнит-тесты в такой манере. Если есть очень много тестов, то должно существенно ускорить их выполнение - как-никак, распределенные вычисления рулят.
http://www.gridgain.org

IceFaces: ajax-реализация JSF, имеет много готовых компонентов, хороший туториал и примеры. Понравилось.
http://www.icefaces.org

Hibernate Shards: технология горизонтального разделения (horizontal partitioning) для популярного ORM-фреймворка. Пока в стадии бета, но активно развивается. Если закладываться на масштабирование системы в будущем, лучше сразу посмотреть на эту разработку.
https://www.hibernate.org/414.htm

понедельник, 13 апреля 2009 г.

j2ee - отдельный проект

Теперь все статьи про java & j2ee, а так же остальную подобную тематику будут размещаться на новом месте - http://j2ee.ucoz.com

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

Старые статьи отсюда будут также перенесены на сайт.

четверг, 11 декабря 2008 г.

Spring Security - kick start

Отличная статья для тех, кто хочет максимально быстро разобраться в интеграции этой технологии в свой проект. Помимо собственно интеграции, также рассматривается модификация стандартной схемы БД для jdbc-user-service, что позволит изменить дефолтную схему по своему усмотрению. На мой взгляд, намного информативнее и полезнее аналогичного примера с сайта Spring.

http://www.mularien.com/blog/2008/07/07/5-minute-guide-to-spring-security

воскресенье, 16 ноября 2008 г.

О масштабируемости систем(ч.3)

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

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

Такой подход имеет отражение в некоторых научных работах, в частности SEDA(Stage Event-Driven Architecture for highly concurrent server applications). 

Из этого следует, что как можно большую часть бизнес-процессов следует реализовывать именно асинхронным образом, поскольку в системах, где время реакции ситсемы на запрос критично, это может существенно снизить время ответа системы. Например, в e-commerce системах время получения ответа пользователем намного важнее, чем время, за которое время запрос будет реально обработан системой. Это позволит пользователю не терять время на ожидание ответа системы, а заняться другими делами, в то время как его запрос будет поставлен в очередь на обслуживание и обработан. В подобных системах нужно придерживаться принципа - "все, что может подождать - должно подождать".

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

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

Правильный выбор кэшируемых данных
Это очень важный момент, поскольку кэширование в определенных случаях способно существенно повысить производительность, а в других - сильно осложнить жизнь. Здесь трудно найти общую закономерность, и принятие решения о том, что следует кэшировать, зависит от конкретного use case. 

Вообще, эффективность кэширования определяется как максимальное cache hit ratio при ограничениях на объем кэшируемой информации, ее доступность и определенным уровнем толерантности к неактуальной информации.

Чаще всего кэшируются по большей части read-only или редко модифицируемые данные, такие как: метаданные, конфиги, словари и т.д. Гораздо более сложными в плане кэширования являются часто обновляемые и часто читаемые данные, поэтому следует хорошо подумать, прежде чем их кэшировать.

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

На днях наткнулся на интересную white-paper, в ней описывается, как снизить нагрузку на сервер БД при использовании Hibernate. Используется технология под названием Terracotta, достаточно известная в настоящее время.

среда, 12 ноября 2008 г.

О масштабируемости систем(ч.2)

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

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

Около 10 лет назад профессор Eric Brewer сформулировал CAP-теорему, согласно которой, среди трех требуемых характеристик распределенной системы: consistency(C), availability(A) и performance(P) одновременно можно выбрать только 2 варианта. Для 24x7 доступной веб-системы, работающей под большой пользовательской нагрузкой придетсся выбрать 2 последние, иначе система не сможет выполнять свое предназначение. Следовательно, consistency придется пожертвовать.

Однако если операция работы с данными производится в рамках одного сервера БД, то тогда вполне можно объединять несколько операций в рамках транзакции или разрешить auto-commit для определенных запросов. Конечно, подобное нарушение принципов ACID не гарантирует немедленную consistency среди всех распределенных частей системы, но взамен этого ситема будет доступна большинство рабочего времени.

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

понедельник, 10 ноября 2008 г.

О масштабируемости систем(ч.1)

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

Система считается масштабируемой, если ее производительность растет как минимум линейно в зависимости от увеличения производительности аппаратной части (увеличили количество серверов вдвое - производительность как минимум вдвое выросла). Чтобы добиться таких показателей, необходимо закладывать определенные архитектурные решения в проект с самого начала. Неправильно спроектированную систему в будущем будет крайне трудно, а то и просто невозможно масштабировать. Рассмотрим основные best-practices, которые мне известны на текущий момент.

Разделение фунциональности
В соответствии с этим необходимо строить систему исходя из того, что отдельные независимые функции системы должны быть автономны друг от друга  и не иметь между собой связей. Подобный принцип реализуется, например, в SOA, и еще именуется принципом функциональной декомпозиции. Это позволит разместить соответствующие части системы на автономные друг от друга группы серверов(например, поиск будет на одном сервере, обслуживание заказов - на другом и т.д.) и регулировать их мощность так же можно будет независимо в зависимости от нагрузки на тот или иной сегмент. Так же это позволит оптимизировать зависимость системы от внешних ресурсов - каждый пул серверов будет иметь доступ только к необходимым для работы ресурсам.
Подобному принципу так же желательно следовать и на уровне БД - распределенные вычислительные мощности будут гораздо лучше себя чувствовать, работая не с одним сервером БД,  а с определенным их множеством. Из этого следует, что одной большой схемы БД не будет - на разных пулах серверов БД будут хоститься только те таблицы, которые нужны для обеспечения работы соответствующего пула серверов приложений, которые имеют к ним доступ. То есть каталог для поисковой подсистемы будет размещен на одном сервере БД, а данные по поставкам или заказам - на другом, в соответствии с функциональным разделением на уровне сервреров приложений.

Горизонтальное разбиение функциональности
Функциональная декомпозиция позволяет достичь определенного прогресса в масштабируемости, однако это далеко не все. Мы должны также иметь возможность разделять общую входящую нагрузку на функциональный блок системы и иметь возможность сбалансированно ее распределять между серверами пула. Для этого можно использовать стандартный load-balancer на уровне серверов приложений, который распределит нагрузку более-менее равномерно. Подразумевается, что каждый экземпляр сервера приложений содержит идентичную и автономную от других функциональность, так что можно просто увеличивать их количество в случае возросшей нагрузки. На уровне БД все обстоит несколько сложнее. Тут необходимо организовывать данные как т.н. "осколки" (shards). Это значит, что например, данные по пользователям равномерно распределены между N серверами БД, аждый из которых хранит свою часть. При этом есть механизм, который автоматически определяет, к какому серверу необходимо обратиться, чтобы получить нужные данные. Естесственно для сервреров приложений это должно быть совершенно прозрачно и они должны быть абстрагированы от деталей реализации. Есть специальные стратегии построения БД для такой конфигурации серверов, как правило, особым образом формируется первичный ключ таблицы, который идентифицирует, на каком сервере будет храниться запись. Хотя наверняка есть и другие варианты, я пока этим вопросом глубоко не занимался.

пятница, 7 ноября 2008 г.

Полезные фреймворки и технологии

Раз уж пока руки не доходят написать за жизнь в Канаде, напишу про джаву :) Узнал парочку весьма полезных в корпоративных проектах фреймворков. Сначала то, что мне, как аналитику по образованию точно бы крайне понравилось. Называется технология OpenRules и предназначена для описания бизнес-правил. Как известно, в реальной жизни редко когда (да практически никогда) бизнес-процессы компании остаются неизменными, так как зачастую зависят от большого количества внешних факторов. Соответственно, если логику зашивать в джава-код, то через достаточно небольшой промежуток времени проблема поддержки приложения станет достаточно остро, т.к. заказчик естесственно захочет иметь автоматизацию своих актуальных бизнес-процессов на текущий момент. Соответственно, нужно будет привлекать как бизнес-аналитика(либо кому-то выполнять его функции), так и разработчиков. Использование же данной технологии позволит все модификации бизнес-правил возложить только на аналитика. И никакой модификации существующего кода! :) Как не трудно догадаться, это происходит потому что бизнес-правила не кодируются, а выносятся на конфигурационный уровень, где их потом можно смело менять и не трогать код. А если точнее - то OpenRules реализует связку Java+MS Excel, где сами правила описываются в интуитивно понятной форме в Excel файле, а потом при помощи движка интегрируются в саму систему. Конечно, есть и техническая часть, но она в большинстве случаев реализуется единожды - при начальном создании набора правил, когда аналитик и разработчик наверняка будут работать в паре. В дальнейшем аналитик как правило будет работать только со своей частью, но конечно при кардинальном изменении требований может обратиться за помощью к tech-guys. Если конечно не осилит внести необходимые изменения самостоятельно. В общем все ясно из картинки:



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

И еще один, не столь глобальный, но очень полезный фреймворк - Dozer. Он умеет.. мапить POJO на POJO :) Может возникнуть вопрос - а на.. зачем это надо? Все просто - эта фича очень плоезна при построении DTO, особенно если DTO содержит в себе информацию из нескольких классов. Написание методов для получения таких объектов вручную лично меня всегда крайне напрягало, поскольку это тупая и обезьянья работа. А при использовании этого фреймворка можно обойтись парой строк вместо пары десятков (сама библиотека достаточно умная и при использовании определенных соглашений количество необходимых телодвижений для получения DTO сводится к минимуму). За что он мне и нравится. Детали - как всегда на сайте производителя :)

четверг, 9 октября 2008 г.

Возврат нескольких значений из метода

Иногда требуется написать метод, в результате выполнения которого возвращается больше, чем одно значение. Как правило для этого пишется аггрегирующий класс(если значения связаны логически), иногда возвращается коллекция со значениями. Если таких методов немного, то с таким подходом еще можно мириться, но в случае, если подобных методов появляется большое количество, код становится труден для понимания и дальнейшей поддержки. В таком случае лучше использовать подход, описанный Брюсом Эккелем в его 4м издании философии Java. Заключается он в использовании generic'ов.

Для каждого кортежа значений создается специальный типизированный класс:

public class TwoTuple {
    public final A first;
    public final B second;

    public TwoTuple(A first, B second) {
        this.first = first;
        this.second = second;
    }
}

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

...
TwoTuple rslt = new TwoTuple(1L, "example");
return rslt;

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