<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6087409723931931873</id><updated>2011-10-10T17:42:30.269-07:00</updated><title type='text'>Groovy &amp; Grails _Ru</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ggru.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ggru.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Viktor_</name><uri>http://www.blogger.com/profile/13297213863840843891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_e5TEQM1cIB4/R-B3h2E8w5I/AAAAAAAAAAM/YHOnb8VlXmo/S220/me.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6087409723931931873.post-5801626235512866275</id><published>2008-04-18T17:51:00.000-07:00</published><updated>2008-04-18T18:09:16.918-07:00</updated><title type='text'>ГрувиМэн (эпизод1) Поможет вам тестировать код</title><content type='html'>&lt;p align=justify&gt;&lt;i&gt;Простой Java программист&lt;/i&gt; уже много дней пишет online игру "Дурак". Пишет на голой Java: сервлеты, jsp странички и javascript. И, конечно же, он использует JUnit для UNIT тестирования. Примерно вот такие вот тесты:&lt;br /&gt; &lt;br /&gt;&lt;code&gt;&lt;br /&gt;Player player1 = new Player ();&lt;br /&gt;player1.setName ("John");&lt;br /&gt;player1.setCards ("6h7h8h9h10h");&lt;br /&gt;&lt;br /&gt;Player player2 = new Player ();&lt;br /&gt;player2.setName ("Bill");&lt;br /&gt;player2.setCards (...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;после чего код по установке кард на столе, колоды и т.д.&lt;br /&gt; &lt;br /&gt;&lt;code&gt;&lt;br /&gt;game.attack (player1, listOfCards);&lt;br /&gt;game.defend (player2, listOfPairs);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt; &lt;br /&gt;и уже после код, которые проверял&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;assert player1.hasCards("h6");&lt;br /&gt;&lt;/code&gt;&lt;br /&gt; &lt;br /&gt;&lt;i&gt;Простой Java программист&lt;/i&gt; расстроен, видя, как много кода занимают тесты. Каждый тест - 15-20 строк (с учетом того, что часть pre и post вызовов выноситься за рамки одного теста). И главное, так лень писать тест за тестом, они такие большие, но, то тут, то там, обнаруживается ошибка, то в AI, то в логике... И нужно бы добавить ещё один тест...&lt;br /&gt;&lt;/p&gt;&lt;br /&gt; &lt;br /&gt;&lt;h2&gt;&lt;br /&gt;Время для ГрувиМэна, который спасет ваш проект, написав билдер для тестирования!&lt;br /&gt;&lt;/h2&gt;&lt;br /&gt; &lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;class TestBuilder {&lt;br /&gt;    def players&lt;br /&gt;    def deck&lt;br /&gt;    def table&lt;br /&gt;&lt;br /&gt;    static runTest(args, closure){&lt;br /&gt;        def tb = new TestBuilder(args)&lt;br /&gt;        closure.delegate = tb&lt;br /&gt;        closure()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def methodMissing(String name, args){&lt;br /&gt;        handle name, args&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def propertyMissing(String name){&lt;br /&gt;        Object[] emptyArray = []&lt;br /&gt;        handle name, emptyArray&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def handle(String name, args){&lt;br /&gt;        def player = players.find {it.name == name.split ('_')[0]}&lt;br /&gt;        def action = name.split ('_')[1]&lt;br /&gt; &lt;br /&gt;        if (action == "Has")&lt;br /&gt;            assert player.hasCards (args[0])&lt;br /&gt;        //we can get a player with this name, and process an action&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class Person{&lt;br /&gt;    def name&lt;br /&gt;    def cards&lt;br /&gt;&lt;br /&gt;    def hasCards (String cards){&lt;br /&gt;        //test&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def john = new Person (name: "John", cards: "6h 7h 8h 9h 10h Kh")&lt;br /&gt;def mike = new Person (name: "Mike", cards: "6s 7s 8s 9s 10s Ah")&lt;br /&gt;&lt;br /&gt;TestBuilder.runTest (players: [john, mike], table:[:], deck:[]){&lt;br /&gt;    John_Attacks ('6h')&lt;br /&gt;    Mike_Defends ('6h': 'Ah')&lt;br /&gt;    John_Has ("7h 8h 9h 10h Kh")&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt; &lt;br /&gt;&lt;p&gt;&lt;br /&gt;Теперь количество строк кода в каждом тесте сократилось в 4-5 раз, тесты стали куда читаемее. &lt;i&gt;Простой Java программист&lt;/i&gt; успокоился, теперь он пишет тесты с радостью, улыбается, смотрит в окно и благодарит ГрувиМэна.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6087409723931931873-5801626235512866275?l=ggru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ggru.blogspot.com/feeds/5801626235512866275/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6087409723931931873&amp;postID=5801626235512866275' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default/5801626235512866275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default/5801626235512866275'/><link rel='alternate' type='text/html' href='http://ggru.blogspot.com/2008/04/1.html' title='ГрувиМэн (эпизод1) Поможет вам тестировать код'/><author><name>Viktor_</name><uri>http://www.blogger.com/profile/13297213863840843891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_e5TEQM1cIB4/R-B3h2E8w5I/AAAAAAAAAAM/YHOnb8VlXmo/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6087409723931931873.post-6550696746185684487</id><published>2008-03-23T18:36:00.001-07:00</published><updated>2008-03-23T18:37:12.174-07:00</updated><title type='text'>Enable Globally</title><content type='html'>&lt;p&gt;ExpandoMetaClass по умолчанию не используется. Например:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Object.metaClass.puts = {obj-&gt;&lt;br /&gt;    println obj&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;puts "hello"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Мы увидим MissingMethodException. Т.е. вся иерархия классов не получает данный метод, только Object. Однако если мы напишем: &lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Integer.metaClass&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;То все объекты класса Integer будут использовать ExpandoMetaClass и начнут понимать puts:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;5.puts “yes”&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Но что, если мы не хотим перечислять все классы в которые мы хотим добавить наш метод? Для этого мы используем:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;ExpandoMetaClass.enableGlobally()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;После чего:&lt;br /&gt;puts “hello”&lt;br /&gt;будет работать везде&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6087409723931931873-6550696746185684487?l=ggru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ggru.blogspot.com/feeds/6550696746185684487/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6087409723931931873&amp;postID=6550696746185684487' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default/6550696746185684487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default/6550696746185684487'/><link rel='alternate' type='text/html' href='http://ggru.blogspot.com/2008/03/enable-globally.html' title='Enable Globally'/><author><name>Viktor_</name><uri>http://www.blogger.com/profile/13297213863840843891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_e5TEQM1cIB4/R-B3h2E8w5I/AAAAAAAAAAM/YHOnb8VlXmo/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6087409723931931873.post-286473120676879420</id><published>2008-03-23T03:06:00.000-07:00</published><updated>2008-03-23T03:10:48.330-07:00</updated><title type='text'>delegate, owner и this (часть 1)</title><content type='html'>&lt;p aling=justify&gt;Эти три переменные очень важны, если вы решили написать DSL. Хотя в простейших случаях они указывают на один и тот же объект, они все могут отличаться друг от друга. Вас не интересовала, как работает identity в Groovy? Быть может, вы думаете, что там кроется какая-та хитрость и только создатели языка да ещё 10-20 программистов знают, как все работает.  &lt;b&gt;Давайте напишем, свой вариант identity и назовем его по старой памяти with.&lt;/b&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class Sample {&lt;br /&gt;    def foo (){&lt;br /&gt;        println "foo"&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    def with (Closure s){&lt;br /&gt;        s.delegate = this&lt;br /&gt;        s ()&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;new Sample ().with {&lt;br /&gt;    foo()&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p aling=justify&gt;&lt;br /&gt;Установив delegate для Closure, мы намекаем Groovy, где искать ненайденные методы - в объекте delegate, в данном случае в объекте Sample. Очень просто? Да.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p aling=justify&gt;&lt;br /&gt;&lt;b&gt;Давайте теперь вздохнем глубоко и напишем:&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class Sample {&lt;br /&gt;    def foo (){&lt;br /&gt;        println "foo"&lt;br /&gt;    }&lt;br /&gt;}    &lt;br /&gt;&lt;br /&gt;ExpandoMetaClass.enableGlobally()&lt;br /&gt;&lt;br /&gt;Object.metaClass.with =  {Closure s-&gt;&lt;br /&gt;    s.delegate = delegate&lt;br /&gt;    s ()&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p aling=justify&gt;&lt;br /&gt;Теперь для любого класса, не только для Sample, будет работать наш with. Опять-таки очень просто. Подробнее о втором примере в следующий раз.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6087409723931931873-286473120676879420?l=ggru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ggru.blogspot.com/feeds/286473120676879420/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6087409723931931873&amp;postID=286473120676879420' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default/286473120676879420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default/286473120676879420'/><link rel='alternate' type='text/html' href='http://ggru.blogspot.com/2008/03/delegate-owner-this-1.html' title='delegate, owner и this (часть 1)'/><author><name>Viktor_</name><uri>http://www.blogger.com/profile/13297213863840843891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_e5TEQM1cIB4/R-B3h2E8w5I/AAAAAAAAAAM/YHOnb8VlXmo/S220/me.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6087409723931931873.post-4341810535494324932</id><published>2008-03-21T04:51:00.000-07:00</published><updated>2008-03-21T05:02:25.770-07:00</updated><title type='text'>Ещё одна отличная книга о Groovy</title><content type='html'>В издательстве Pragmatic Programmer готовится к печати ещё одна книжка по Groovy: &lt;span style="font-weight: bold;"&gt;Venkat Subramanian – Programming Groovy&lt;/span&gt;. Вы можете купить её за 20 долларов в формате PDF. Найти её бесплатную я так и не сумел, поэтому пришлось раскошелиться. Стоит отметить, книжка стоит этих 470 рублей.&lt;br /&gt;&lt;br /&gt;Книга состоит из трех основных частей: &lt;span style="font-weight: bold;"&gt;Beginning Groovy, Using Groovy, MOPing Groovy&lt;/span&gt;. Я уже довольно длительное время программирую на Groovy, написал на нем пару проектов, поэтому первые две части особого интереса для меня не представляли. Кроме разве что главы про Closures: более доступно объяснить разницу между owner, this, delegate мне кажется невозможно.&lt;br /&gt;&lt;br /&gt;Но  покупал то я эту книгу ради раздела про метапрограммирование.  Читая в Groovy In Action главу про MOP я как-то не очень проникся, да и с того времени Groovy сильно нарастил свои метапрограммисткие мышцы.  Я надеялся, что книжка Венката поможет мне не плавать в этой теме. Надежды оправдались, раздел про MOP написан блестяще. Очень подробно, в деталях, описывая все нюансы, &lt;span style="font-style: italic;"&gt;автор просто вбивает вам в голову знание MOP&lt;/span&gt;.  Он начинает с азов, а затем демонстрирует все возможные методы синтеза кода и заканчивает главами о тестировании (очень подробно: отдельно о том, как тестировать Java и Groovy), построении билдеров и написании DSL.  &lt;span style="font-style: italic;"&gt;Дочитав до конца, я включил консоль и без труда, без особых размышлений «как», написал два DSL.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Как мне кажется, книжка все-таки больше пригодится тем, кто уже пишет на Groovy. Венкат доступно и очень информативно описывает многие тонкости языка: тестирование, метапрограммирование и др. Да, самое главное: &lt;span style="font-weight: bold; font-style: italic;"&gt;после прочтения я определенно стал понимать Groovy лучше.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6087409723931931873-4341810535494324932?l=ggru.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ggru.blogspot.com/feeds/4341810535494324932/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6087409723931931873&amp;postID=4341810535494324932' title='Комментарии: 6'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default/4341810535494324932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6087409723931931873/posts/default/4341810535494324932'/><link rel='alternate' type='text/html' href='http://ggru.blogspot.com/2008/03/groovy.html' title='Ещё одна отличная книга о Groovy'/><author><name>Viktor_</name><uri>http://www.blogger.com/profile/13297213863840843891</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp1.blogger.com/_e5TEQM1cIB4/R-B3h2E8w5I/AAAAAAAAAAM/YHOnb8VlXmo/S220/me.png'/></author><thr:total>6</thr:total></entry></feed>
