среда, 26 января 2011 г.

Groovy - легкий вызов метода по его имени

В Java вы не можете вызвать метод динамически по его имени или полной сигнатуре, вам надо лезть в Reflection API, получить Class объекта, получить список его методов, получить объект класса метода (Method), и вызвать на нем methodObject.invoke(params).

В Groovy это чуть проще... Примерно вот так:


public class TestClass{

    public testA(){println "Called A"}
    public testB(){println "Called B"}
    public testC(){println "Called C"}
    public testD(){println "Called D"}
}

def methodName = 'testA'
TestClass test = new TestClass()
test."$methodName"()
Печатает как можно догадаться, Called A.

вторник, 25 января 2011 г.

Немного мыслей про будущее платформы Java

Навеяно обсуждениями тем для следующего подкаста Radio-T: http://radio-t.com/temi_dlja_vipuskov/temy-dlya-224/

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


Итак.

Java изначально позиционировалась как платформенно-независимый язык программирования. Подчеркну, не платформа, а именно кроссплатформенный язык.  Такой, чтоб  write once, run anywhere. Т.е. несмотря на то, что архитектура стековой машины JVM и структура байткода позволяла и позволяет портировать другие языки под JVM, сановцы никогда не делали на это акцент. Акцент всегда был на том, что есть JVM, которая работает везде, есть байт-код, который не зависит от архитектуры, нет указателей и прочего прямого доступа к памяти, что круто. А потому пишите на Java (языке) и будет вам счастье.

Сравним это с позиционированием .NET, C# и позицию Майкрософта здесь. Еще когда я учил C# 2.0 по книжке Эндрю Троелсена лет так 5 назад (это было до моего  перехода на Java ;)),  там напротив, было везде написано, что .NET  и его компоненты, в частности среда CLR - это среда для хостинга промежуточного управляемого кода. C#, VB#, managed C++ (который не особо выстрелил, но эксперимент был проведен), и всякие языки портированные под .NET, типа IronPython и иже с ними, а так же новые языки, развиваемые Microsoft Research, типа F#.

При этом, например, Майкрофост кроме того, что быстро развивает "основной" язык, С#, еще и  активно вкладывается а разработку других языков под дотнет. Например, F#, который перенял очень многие концепции из Haskell-а. Код на F# буквально очень похож на код на хаскелле, уверяю!  MSSQL сервер так же умеет хостить CLR и поддерживает, насколько я знаю, написание хранимых процедур на нем.

А теперь вернемся к миру Java. Итак -Java, как платформа и как язык, развивается медленно под сравнению с C#  и .NET, это очевидно. Возможно, это правильно, так как миру Enterprise-а (банки, биржи и т.п.)  важнее стабильность, а не быстрое развитие.

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

С другой стороны, есть Groovy, Scala, для желающих чего-то более необычного - Closure. При этом эти языки написаны и отлаживаются либо группами комьюнити (например, Groovy разрабатывается SpringSource комьюнити), либо на гранты (как Scala, получившая недавно крупный грант Евросоюза). Со стороны Sun/Oracle поддержки тут я не вижу, ну кроме разве что введения инструкции InvokeDynamic в 7 Java, но этого мало. Мало и слишком медленно.

В общем, на мой взгляд, Java имеет огромный шанс еще очень долго держать лидерство как платформа, если вложится в развитие и, главное, продвижение (!) основных альтернативных языков под JVM. Это то, что рекламировали маркетологи .NET как один из мощных плюсов платформы с самого начала.

"Пишите на вашем любимом языке, будь то старая добрая Java,  лаконичный Groovy с его языковым сахаром и метапрограммированием,  изощренная и немного академичная Scala, или Closure (тут без эпитетов, ибо не трогал, не знаю),  - и запускаете на стандартной, надежной, проверенной (миллион эпитетов)  платформе Java".

Как вам?


четверг, 20 января 2011 г.

Groovy switch magic

Рассмотрим такой простой и тривиальный оператор, как switch. Казалось бы, ну что можно придумать нового вокруг него? Ан-нет, можно.


В Java как известно, switch-ить можно только по целым числам и по Enum-ам, и все это жестко зашито в синтаксисе языка. Остальное - запрещено. В Groovy же этот оператор работает следующим образом.


Общая логика работы оператора switch проста и знакома каждому программисту:

switch (candidate) {
  case classifier1 : handle1() ; break
  case classifier2 : handle2() ; break
  default : handleDefault()
}
А теперь надо вспомнить, что в Groovy, в отличие от Java, "все есть объект". Т.е. абсолютно все, без исключений в виде примитивных типов. Соответственно, classifier1, classifier2 и candidate - объекты. И для того, чтобы вышеприведенная конструкция работала, необходимо и достаточно, чтобы classifier 1 и classifier2 имели метод isCase(candidate), возвращающий булево значение. Все просто.
И еще несколько ценных свойств свитчей в Groovy. 
Во-первых, классификаторы classifier1 и classifier2 вовсе не обязаны быть одного и того же типа. Во-вторых, выражение-candidate может удовлетворять нескольким case-ам, а не одному. Откуда следует, что порядок case-ов в Groovy, в отличие от Java,  важен.


Ну и небольшой пример, что можно делать в switch-ах в Groovy:

switch (20) {
   case 2 : assert false ; break // Равно двум?
   case 2..15 : assert false ; break // Попадает в диапазон?
   case [11,12,14,16] : assert false ; break // Входит в список?
   case Double : assert false ; break // является Double-типом?
   case {it % 5 == 0}: assert true ; break // Делится на пять?
   case ~/../ : assert true; break // В эту ветку мы не заходим
   default : assert false ; break
}

понедельник, 17 января 2011 г.

Groovy - регулярные выражения на уровне синтаксиса языка

По сравнению с Java, в Groovy регекспы поддерживаются на уровне языка. Маленький пример.

def source = 'this is some string just string plain string'

// во-первых, есть спец. форма записи строки, 
//в которой не требуется квотирование
word = /\w+/ 

// оператор ~ позволяет прекомпилировать объект паттерна (так же поддерживает
// подстановку подстрок). wholePattern тут - объект типа java.util.regex.Pattern
wholePattern = ~/($word $word)*/ 

// это проверка (оператором ==~) что вся строка содержит 
// только слова, разделенные пробелами.
assert source ==~ wholePattern 

// А это матчинг, операторв =~ создает объект матчера (java.util.regex.Macher).
// Проверяем, что данному паттерну сооттствует три подстроки
def finder = (source =~ "st..ng*")
assert finder.getCount() == 3

понедельник, 10 января 2011 г.

Мартин Фаулер, Шаблоны корпоративных приложений

Книжка на озоне

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

Прочитал. Читал несколько месяцев, с хрипом и одышкой. Однако, после прочтения появилось ощущение, что я немножко лучше понял Дао :). Рекомендую.







Коротко,

Плюсы:

  • Одна из немногих книг по Enterprise разработки, которая не привязана к определенным технологиям, таким как EJB, Corba, Struts, ADO.NET и прочие. Тем самым позволяет концентрироваться на паттернах, а не на идиомах.
  • Хорошая подборка из более чем 40 паттернов. For reference. Описаны многие вещи, которые где-то краем уха слышал, а обобщить/проработать глубоко и системно как-то не получалось. Например - паттерны Active Recods, Table/Row Data Gateway и прочие.
  • Есть интересный материал по концепциям и реализации ORM. Очень полезно как для тех,  кто привык писать все через его величество Hibernate / Apache Cayene / iBatis, так и для тех, кто в силу разных причин использует (или пишет) свой собственный ORM. Вообще говоря, если вы пишете свой ORM, вам надо прочитать этот пост - Неделя борьбы с велосипедизмом :). В часности, описаны различные способы примирить один из столпом ООП -наследование - с реляционной алгеброй. Single table inheritance, class table inheritance и все такое. Я в который раз порадовался, что мы в своем проекте успешно обходимся (уже 7 лет как) без наследования вовсе (в пределах доменной модели).
  • Хорошо описаны паттерны трекинга состояния сеанса и оптимистичных / пессимистичных блокировок.
  • Помимо прочего, между делом часто просто, коротко и доступно описываются такие не всем известные вещи, как thread-local register, separated interface, special case и прочие.
  • Примеры даны как на Java, так и на C#.
  • Автор не преподносит свои идеи как догмы, а напротив, все время философски указывает, что "я скорее склонен делать это так, однако другие решения так же могут работать", "никто не знает вашу задачу лучше вас, поэтому решайте сами", "возможно в течении нескольких ближайших лет все в этой области изменится."
Минусы:

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

Как программисты смотрят друг на друга

http://axgle.github.com/images/haskell.jpg - некоторая истина в этой картинке есть. Довольно точно, я считаю, отображает мнение большинства в каждой категории.