Wednesday, December 17, 2008

О Rails

Dave Thomas ещё до появления Rails говорил, что Ruby будет следующей вехой и что нам всем приказано ждать прихода этого языка в большой энтерпрайз. Не дождались, за последние несколько месяцев популярность этого языка по данным TIOBE даже несколько упала. Все попытки запускать Rails на Glassfish конечно же похвальны, но это как увешать ослика шарами и запустить. Он конечно полетит. но это вам надо? И ослику этого тоже не надо. Все ваши попытки сделать из него расчудесного летающего осла ему совсем не по душе.

Saturday, December 13, 2008

Путь джедая

Язык Java мне надоел. Надоел потому как все мысли, что я пытаюсь выразить на нем, находят намного более простое и короткое выражение на таких языках как Groovy и Scala. Я убежден, чтобы стать джедаем Java платформы нужно знать эти два замечательных языка.

На работе, мы используем Groovy для описания предметной области. Мы написали несколько DSL и в разы сократили количество кода. У нас есть проект на Grails. А ещё несколько месяцев назад их не было. Уже планируется написание небольшой утилитки на Scala.

Вы скажете, что у вас все не так. Бородатые дядьки не дают вам писать тесты на Groovy, не дают вам писать в 3 раза более короткий код на Scala. Вполне может быть. А вы все равно читайте. Если каждый почитает, каждый прочувствует, каждый поймет, что это здорово, то дело сдвинется.

Friday, April 18, 2008

ГрувиМэн (эпизод1) Поможет вам тестировать код

Простой Java программист уже много дней пишет online игру "Дурак". Пишет на голой Java: сервлеты, jsp странички и javascript. И, конечно же, он использует JUnit для UNIT тестирования. Примерно вот такие вот тесты:


Player player1 = new Player ();
player1.setName ("John");
player1.setCards ("6h7h8h9h10h");

Player player2 = new Player ();
player2.setName ("Bill");
player2.setCards (...



после чего код по установке кард на столе, колоды и т.д.


game.attack (player1, listOfCards);
game.defend (player2, listOfPairs);


и уже после код, которые проверял


assert player1.hasCards("h6");


Простой Java программист расстроен, видя, как много кода занимают тесты. Каждый тест - 15-20 строк (с учетом того, что часть pre и post вызовов выноситься за рамки одного теста). И главное, так лень писать тест за тестом, они такие большие, но, то тут, то там, обнаруживается ошибка, то в AI, то в логике... И нужно бы добавить ещё один тест...




Время для ГрувиМэна, который спасет ваш проект, написав билдер для тестирования!




class TestBuilder {
def players
def deck
def table

static runTest(args, closure){
def tb = new TestBuilder(args)
closure.delegate = tb
closure()
}

def methodMissing(String name, args){
handle name, args
}

def propertyMissing(String name){
Object[] emptyArray = []
handle name, emptyArray
}

def handle(String name, args){
def player = players.find {it.name == name.split ('_')[0]}
def action = name.split ('_')[1]

if (action == "Has")
assert player.hasCards (args[0])
//we can get a player with this name, and process an action
}
}

class Person{
def name
def cards

def hasCards (String cards){
//test
}
}

def john = new Person (name: "John", cards: "6h 7h 8h 9h 10h Kh")
def mike = new Person (name: "Mike", cards: "6s 7s 8s 9s 10s Ah")

TestBuilder.runTest (players: [john, mike], table:[:], deck:[]){
John_Attacks ('6h')
Mike_Defends ('6h': 'Ah')
John_Has ("7h 8h 9h 10h Kh")
}



Теперь количество строк кода в каждом тесте сократилось в 4-5 раз, тесты стали куда читаемее. Простой Java программист успокоился, теперь он пишет тесты с радостью, улыбается, смотрит в окно и благодарит ГрувиМэна.

Sunday, March 23, 2008

Enable Globally

ExpandoMetaClass по умолчанию не используется. Например:




Object.metaClass.puts = {obj->
println obj
}

puts "hello"


Мы увидим MissingMethodException. Т.е. вся иерархия классов не получает данный метод, только Object. Однако если мы напишем:



Integer.metaClass


То все объекты класса Integer будут использовать ExpandoMetaClass и начнут понимать puts:



5.puts “yes”

Но что, если мы не хотим перечислять все классы в которые мы хотим добавить наш метод? Для этого мы используем:



ExpandoMetaClass.enableGlobally()


После чего:
puts “hello”
будет работать везде

delegate, owner и this (часть 1)

Эти три переменные очень важны, если вы решили написать DSL. Хотя в простейших случаях они указывают на один и тот же объект, они все могут отличаться друг от друга. Вас не интересовала, как работает identity в Groovy? Быть может, вы думаете, что там кроется какая-та хитрость и только создатели языка да ещё 10-20 программистов знают, как все работает. Давайте напишем, свой вариант identity и назовем его по старой памяти with.




class Sample {
def foo (){
println "foo"
}

def with (Closure s){
s.delegate = this
s ()
}
}

new Sample ().with {
foo()
}



Установив delegate для Closure, мы намекаем Groovy, где искать ненайденные методы - в объекте delegate, в данном случае в объекте Sample. Очень просто? Да.




Давайте теперь вздохнем глубоко и напишем:




class Sample {
def foo (){
println "foo"
}
}

ExpandoMetaClass.enableGlobally()

Object.metaClass.with = {Closure s->
s.delegate = delegate
s ()
}



Теперь для любого класса, не только для Sample, будет работать наш with. Опять-таки очень просто. Подробнее о втором примере в следующий раз.

Friday, March 21, 2008

Ещё одна отличная книга о Groovy

В издательстве Pragmatic Programmer готовится к печати ещё одна книжка по Groovy: Venkat Subramanian – Programming Groovy. Вы можете купить её за 20 долларов в формате PDF. Найти её бесплатную я так и не сумел, поэтому пришлось раскошелиться. Стоит отметить, книжка стоит этих 470 рублей.

Книга состоит из трех основных частей: Beginning Groovy, Using Groovy, MOPing Groovy. Я уже довольно длительное время программирую на Groovy, написал на нем пару проектов, поэтому первые две части особого интереса для меня не представляли. Кроме разве что главы про Closures: более доступно объяснить разницу между owner, this, delegate мне кажется невозможно.

Но покупал то я эту книгу ради раздела про метапрограммирование. Читая в Groovy In Action главу про MOP я как-то не очень проникся, да и с того времени Groovy сильно нарастил свои метапрограммисткие мышцы. Я надеялся, что книжка Венката поможет мне не плавать в этой теме. Надежды оправдались, раздел про MOP написан блестяще. Очень подробно, в деталях, описывая все нюансы, автор просто вбивает вам в голову знание MOP. Он начинает с азов, а затем демонстрирует все возможные методы синтеза кода и заканчивает главами о тестировании (очень подробно: отдельно о том, как тестировать Java и Groovy), построении билдеров и написании DSL. Дочитав до конца, я включил консоль и без труда, без особых размышлений «как», написал два DSL.

Как мне кажется, книжка все-таки больше пригодится тем, кто уже пишет на Groovy. Венкат доступно и очень информативно описывает многие тонкости языка: тестирование, метапрограммирование и др. Да, самое главное: после прочтения я определенно стал понимать Groovy лучше.