воскресенье, 18 апреля 2010 г.

Java - отличная платформа, но слишком неповоротливый язык.

Хотел поделится порцией очевидностей. Java - это действительно отличная платформа для разработки, с больших комьюнити, огромным числом Open Source библиотек, инструментов и т.п. Но вот язык Java этой платформы слишком устарел. Лично я не поклонник нагромождения синтаксического сахара, как например в Ruby. Но я сравниваю с C# и там есть много действительно полезных плюшек, практически полезных (я вообще пишу только о том, с чем лично столкнулся).
Вот два небольших примера.
1. Есть очень популярная задача, организовать конвейер для обработки документов, которые по сути из себя представляют Map или, если говорим о C#, Dictionary. К Dictionary в дот нете, у меня есть одна большая претензия, он слишком часто кидает исключения. Но речь не об этом. Вот так выглядит простой документ, я добавил в него метод AddProperty, с помощью которого можно не только добавить элемент, но и перезаписать старый:
  1. public class Document : Dictionary<stringobject>  
  2.     {  
  3.         public Document AddProperty(string name, object value)  
  4.         {  
  5.             if (ContainsKey(name))  
  6.                 Remove(name);  
  7.   
  8.             Add(name, value);  
  9.             return this;  
  10.         }  
  11.     }  
Собственно ничего интересно, за исключение полезной штучки, метод возвращает не void, а самого себя.
API конвейера тоже простое:
  1. public class Pipeline  
  2. {  
  3.     public void AddProccessor(Func<Document, Document> proccessor)  
  4.     {  
  5.     }  
  6.   
  7.     public void Execute()  
  8.     {  
  9.     }  
  10. }  
Вот тут почти самый главный момент. Делегаты это хорошо, мне надоели в том же свинге листенеры с одним методом, это ужас какой-то.
Но самое интересное теперь. Иногда требуется добавить очень простую обработку, которая просто добавляет пару полей к документу. В java пришлось бы поступить как в свинге, анонимный класс с реализацией метода интерфейса листенера. Но в C# коллега подсказал очень и очень красивое решение:
  1. var pipeline = new Pipeline();  
  2. pipeline.AddProccessor(record => record.AddProperty("NewProp""Value").AddProperty("AnotherProp", 1));  
Действительно в одну строчку.
2. На эту тему копий сломано не мало, перегрузка методов или параметры по умолчанию. Кто бы, что ни говорил, но C# 4.0 c параметрами по умолчанию плюс именование параметров, лично для меня, отличное, красивое и удобно решение.
Вот есть метод:
  1. public static string format(string value,   
  2.             bool option1 = falsebool option2 = false)  
  3. {  
  4.     return value;  
  5. }  
Параметры по умолчанию позволяют не забивать и так не маленькие исходные тексты кучей не нужного текста. Но к сожалению они не идеальны без одной маленькой штучки. Вот скажите, что надо сделать, чтобы вызвать описанный метод, но чтобы option2 был true. Придется или перегружать метод, или при вызове передавать false для option1. Но проблема решена в C# 4.0. При вызове метода передаваемые параметры можно именовать, так что теперь можно не беспокоиться об очерёдности параметров, а также решить указанную выше проблему простым способом:
  1. format("test", option2: true);  
Да, для JVM есть много интересных альтернативных языков, например мне нравится Clojure. Но например у него есть проблемы с производительности и вообще, его активно портируют на CLR. Хотелось бы, чтобы и основной язык платформы более активно развивался.

Ну и так, ещё одна рабочая мысль за сегодня: парное программирование - это не только весело, но и действительно продуктивно.

И совсем напоследок цитата дня (которую правда уже постил в Buzz'е, но уж больно понравилась):
  1. select fun, profit from real_world where relational=false  

7 комментариев:

  1. Интересные мысли. При переходе с С++ на Java очень нахватало 'значений параметров по умолчанию' и 'указателей на функцию'.
    Но с другой стороны это ковбойством каким-то попахивает:) Я бы не назвал код в третьем листе таким уж очевидным. Да и 'в одну строчку' тоже довольно спорно (при стандартной длине строки в 80).

    ОтветитьУдалить
  2. Знаете, не ковбойство это помоему. А когда имя параметра указываешь, то даже читается лучше однозначно. Параметры по умолчанию это не плохо, лучше чем стопитсот перегрузок метода. Указатели на функцию действительно лажовая штука, лучше функции высшего порядка :) Вообщем давно облизываюсь на Scala и пр. Лиспы и функциональщину, просто надо ещё мозг повернуть, чтобы этим правильно пользоваться...
    Ну, а про 80 симвалов... не знаю, у меня даже на работе 19" :) а вообще можно разнести на несколько строчек, но при этом код все равно будет более читаемым по моему чем Java.
    Насчёт интересности не знаю. просто иногда накипает :))
    Спасибо за комментарий.

    ОтветитьУдалить
  3. У каждого свое ИМХО, но все же:
    format("test", option2: true);
    1. Имея только эту строку практически невозможно сказать сколько аргументов принимает метод.
    2. Нужно сделать дополнительные телодвижения, чтобы понять что такое option2:.
    Мне кажется, что если код будет наполнен такими вот вызовами, то это только затруднит его изучение.

    По поводу облизывания на Scala и пр. Лиспы и функциональщину: надо постараться попасть на соответсвующий проект, а там могзи сами повернутся :)

    ОтветитьУдалить
  4. > 1
    Благодаря перегрузке методов, такой же эффект достигается, считаю, что это не критично
    > 2
    Просто параметры не правильно названы, можно и понятнее сделать.
    > По поводу облизывания на Scala....
    Таки в наших краях очень сложно, освобождаю время, чтобы начать какой-нибудь свой midnight проект... :)

    ОтветитьУдалить
  5. public Document AddProperty(string name, object value) { if (ContainsKey(name)) Remove(name); Add(name, value); return this; }

    А почему вместо этого не написать

    this[name] = value;

    ?

    Вроде эквивалентно будет.

    ОтветитьУдалить
  6. Всё правильно, но как говориться: привычка - вторая натура. Т.е. возвращаемся к заголовку статьи :) Это всё противная java, очень не привычно с чем-то кроме массивов работать через [] =\

    ОтветитьУдалить
  7. Да... пытались меня как-то на java перевести после C# 3... неудачно. То есть, язык вменяемый, все понятно, ясно как делать... но писать море кода там, где раньше был iterator block, или кучку вложенных циклов-условий-снова-циклов где раньше был трехстрочный LINQ-запрос...


    Сбежал я оттуда, в общем :)

    ОтветитьУдалить