понедельник, 31 августа 2009 г.

Bean Validation

JSR303 Кажется весьма интересным стандартом. Система валидации данных наверное один из самых старейших велосипедов известных мне. Защитное программирование требует чтобы проверялись все входные параметры метода, что выливается в блоки проверки правильности данных в каждом методе, что в свою очередь ведет к повторению кода - а это нарушает принцип DRY. Вот наконец-то светлые умы мира JAVA добрались и до этой проблемы. Прежде чем рассказать о стандарте, пример:

package test.validator;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

public class User {

@NotNull(message="Имя должно быть задано")
String firstname;

@NotNull(message="Фамилия должна быть задана")
@Size(min = 3, message="Длина фамилии должна быть больше трех")
String lastname;

@NotNull(message="Имэйл должен быть задан")
@Pattern(regexp = "^(?:[a-zA-Z0-9_'^&/+-])+(?:\\.(?:[a-zA-Z0-9_'^&/+-])+)" +
"*@(?:(?:\\[?(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))\\.)" +
"{3}(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\]?)|(?:[a-zA-Z0-9-]+\\.)" +
"+(?:[a-zA-Z]){2,}\\.?)$",
message = "заданный имэйл не может существовать")
String email;

@Override
public String toString() {
return String.format("firstname: [%s], lastname: [%s], email: [%s]",
firstname, lastname, email);
}

public static void validate(Object object, Validator validator) {
Set<constraintviolation<object>> constraintViolations = validator
.validate(object);

System.out.println(object);
System.out.println(String.format("Кол-во ошибок: %d",
constraintViolations.size()));

for (ConstraintViolation<object>l; cv : constraintViolations)
System.out.println(String.format(
"Внимание, ошибка! property: [%s], value: [%s], message: [%s]",
cv.getPropertyPath(), cv.getInvalidValue(), cv.getMessage()));
}

public static void main(String[] args) {
ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
Validator validator = vf.getValidator();

User user = new User();
validate(user, validator);

user.firstname = "Вася";
validate(user, validator);

user.lastname = "Пу";
validate(user, validator);

user.lastname = "Пупкин";
validate(user, validator);

user.email = "вася пупкин@example.com";
validate(user, validator);

user.email = "vasya.poupkine@example.com";
validate(user, validator);

}
}


Обратите внимание на аннотации:
* Логические: @NotNull, @NotEmpty, @AssertTrue/False
* Бизнес: @Email, @EAN, @CreditCard
* Значение: @Min, @Max, @Digits, @Length, @Size
* Другие: @Valid, @Pattern
* Свои собственные!

Жду имплементации в JPA 2.0

воскресенье, 23 августа 2009 г.

Фактор стабильного сервиса

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

понедельник, 17 августа 2009 г.

Сжатый опыт J2ME

Встала задача разработать интерфейс к нашей платежной системе на сотовые телефоны. Опыт разработки приложений подобного класса у меня уже был и весьма отрицательный. Первое мое приложение было собрано с помощью волшебника Netbeans. Весь процесс разработки свелся к тасканию окошек и раставлению стрелок между ними. В итоге, по прошествии нескольких циклов разработки Netbeans отказывался грузить такую огромную схему, а разобраться в хитросплетениях самогенерированного кода было уже не судьба. Благо что проект успел закончиться, прежде чем он окончательно вышел бы из под контроля.

За новое приложение на платформе J2ME я уже взялся с колокольни своего опыта разработки на Java. Бодро нашлись удобные инструменты, вроде готового окошечного виджетового фреймворка Kuix, IOC контейнера israfil-micro-container и даже ORM фреймворк Floggy. Для связи воспользовался SOAP библиотека kSOAP 2.

Отдельно про плюсы и минусы каждой части приложения:

Kuix - большой виджетовый фреймворк с активным коммунити, которое задает одни и теже вопросы на форуме по 10 раз как минимум. Так что любая проблема встреченная вами при работе с этим фреймворком будет обсосана со всех сторон и часто не решена. Фреймворк преследует цель одинаково работать на максимальном количестве устройств. В нашем же случае можно было ограничиться изделиями фирмы Nokia и не тестировать приложение на зоопарке других девайсов. Больше всего меня впечатлила поддержка css данной библиотекой. Оказалось очень удобно сначала сформировать workflow приложения без оглядки на внешний вид, а потом обработать напильником. Работа с данным фреймворком очень похожа на веб разработку. К минусам можно отнести большой вес и необходимость большой вычислительной мощности. На бюджетных сотках за 1700 сом приложение неумолимо выбрасывает OutOfMemoryException.

Israfil - IOC контейнер. В принципе больше нечего о нем сказать. Рома однажды сказал: "нафиг он тебе нужен". Да Рома, он нафиг не нужен, куда удобней работать с singleton'ом ObjectCreator.

Floggy - ORM. Прикольная штука. Кормишь ей объект, кушает. Просишь обратно, отрыгивает. Работает именно так как должна. Мне понравилось. Тем более у меня был опыт работы с API RMS. Мне оно активно не понравилось ибо приходится много думать и много тестировать. Зачем лишний геморой?

kSOAP 2 - Поддержка данной библиотеки сдохла еще в 2006, но к моему удивлению они смогли написать что-то, что работает. Единственный минус - библиотека не умеет работать с cookie. Пришлось ее научить, это оказалось не сложным, просто переписал пару классов. Но тот факт, что можно работать с RPC SOAP радует. Можно целиком избавиться от слоя сервлетов, которые мне честно говоря уже очень надоели. Я уже нашел библиотеку работы с SOAP на JS. Как показала практика бизнес логику удобно держать в виде web сервисов, тогда можно писать различные интерфейсы: веб, для мобильников, десктопные и с легкостью объединять с другими системами, что в бизнес приложениях не редкость.

Как было уже упомянуто, большая часть наших клиентов ходит с сотками очень бюджетного класса, на которых приложение отказалось работать. Я был огорчен неверным построением требований. Но благо это обернулось малой кровью. Благодаря слоистой структуре изменениям подвергся только слой представления. Всего 2 дня работы и интерфейс был переписан на привычный lcdui. Пришла мысль чего я парился? На lcdui разработка куда легче, работает быстрее и весит меньше... разве что интерфейсы получаются однообразные. Но для бизнес приложения это невеликий недостаток.

Когда я рассказывал Роме о приложении примерно в тех же словах, что и вам, он спросил: "а как тестируешь?". Я не тестирую, вернее тестирую, но вручную, у меня нет автоматических тестов на данное приложение. Почему? Сначала я попробовал их писать на привычном jUnit, но столкнулся с проблемой, что приложение запускается на J2ME, а тесты на J2SE. А между этими платформами параллелей не много... Существует тестовый фреймворк для J2ME, но мне показалось излишним париться с тестами, когда фактического функционала немного и проще перед релизом просто проверить все тестовые случаи вручную.

Пару лет назад я читал статью, где утверждалось, что J2ME умер, так как появились сотки достаточно мощные, чтобы запускать J2SE. Но вот, 2 года прошло, а нам экономически выгодно писать приложения на J2ME. Пользователей и сейчас очень много. Среди кассиров почти не встретишь людей, грузящих еды через iPhone или GAndroid...

PS: Никита привет, ты единственный, кто подписан на RSS моего блога, сделай в google reader общей статьей :)