Re[2]: Приемы программирования на Java
От: Blazkowicz Россия  
Дата: 06.02.09 13:50
Оценка:
Здравствуйте, techgl, Вы писали:

T>А то в Java параметризировать методы нельзя.

Можно.
Re[3]: Приемы программирования на Java
От: techgl  
Дата: 06.02.09 13:54
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

T>>А то в Java параметризировать методы нельзя.

B>Можно.
Статические, как я понял, нельзя. Или приведи пример, какой код будет компилироваться, пожалуйста.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Приемы программирования на Java
От: Blazkowicz Россия  
Дата: 06.02.09 13:59
Оценка: 2 (1)
Здравствуйте, techgl, Вы писали:

T>>>А то в Java параметризировать методы нельзя.

B>>Можно.
T>Статические, как я понял, нельзя. Или приведи пример, какой код будет компилироваться, пожалуйста.

      public <T> Set<T> set(T... ts) {
        return new HashSet<T>(Arrays.asList(ts));
      }

Там как раз пропущен указатель на то что метод Generic.
Re[2]: Приемы программирования на Java
От: mazurkin http://mazurkin.info
Дата: 06.02.09 14:00
Оценка:
techgl wrote:
> Здравствуйте, Евгений Кирпичев aka jkff, Вы писали:
>
> Хорошая статья.
> Однако столкнулся с непонятной реализацией. Речь о помощнике для статических коллекций. Из статьи:
>
> public class CollectionUtils {
> 
>   public static Set<T> set(T... ts) {
>     return new HashSet<T>(Arrays.asList(ts));
>   }
> 
> }
>


Вообще вот так должно быть

    public static <T> Set<T> set(T... ts) {
        return new HashSet<T>(Arrays.asList(ts));
    }
Posted via RSDN NNTP Server 2.1 beta
Re[5]: Приемы программирования на Java
От: techgl  
Дата: 06.02.09 14:03
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Там как раз пропущен указатель на то что метод Generic.

Да, невнимательно посмотрел в спецификацию. Спасибо.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Приемы программирования на Java
От: DenLion Россия  
Дата: 24.08.09 14:42
Оценка:
Здравствуйте, Евгений Кирпичев aka jkff, Вы писали:

ЕКA>Статья:

ЕКA>Приемы программирования на Java
Автор(ы): Евгений Кирпичев aka jkff
Дата: 28.12.2008
Официально язык Java поддерживает только объектно-ориентированную парадигму, которая не всегда позволяет сделать код компактным, легко читаемым и удобным в поддержке. Однако Java-гуру умудряются использовать имеющиеся в Java возможности для применения в Java-коде функционального стиля программирования, который в некоторых случаях позволяет радикально улучшить читаемость кода (делая его более декларативным), а также упростить его поддержку и развитие. Надеемся, что данная статья будет полезна многим Java-программистам разного уровня.
Большая часть данной статьи не имеет отношения к собственно функциональному программированию (далее – ФП). В основном будут рассмотрены способы повышения читаемости некоторых часто встречающихся паттернов, особенно при использовании функционального стиля, и без которых об ФП не может быть и речи. О приемах собственно ФП будет сказано совсем немного, ближе к концу статьи.


Очень интересная статья, спасибо. Но есть одно некоторые ньюансы: у нас в проекте есть блок статической
инициализации мапа из более чем 4ёх десятков строк для пары ключ->значение, где каждый
ключ и каждое значение есть стринг из более чем 30ти (до 50ти) символов. В таком случае, мне кажется,
читаемость "обычного стиля" (someMap.put(CONSTANT_WITH_LONG_NAME, "anotherStringConstant")) будет
выше. При попытке перевести эту громадину на предлагаемый вами стиль получится страшная каша.
Re: Приемы программирования на Java
От: vip_delete  
Дата: 24.08.09 19:13
Оценка: +1 -3
Вставлю свои 5 копеек. Статья из серии холивара, как надо писать и как не надо.

Мне, например, не все приемы из статьи понравились, а некоторые доведены до абсурда.

1. Вначале статьи автор пишет, что будет бороться с "kingdom of nouns", а потом предлагает для большей читаемость насоздавать кучу своих классов и используя static import заимпортировать в свои классы. Например, класс

public abstract class Filters 
{
  public static Filter and(Filter a, Filter b) {return new AndFilter(a,b);}
}


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

Filter f = new AndFilter(first, second);


То же самое можно сказать про "Конструкторы с сигнатурами базового класса". Если это пустые классы, то это как раз те самые "kingdom of nouns", с которыми борется автор.

2. На мой взгляд, главное, чтобы код читался хорошо, хотя бы теми кто его пишет. Например, код

private static final Set<String> INTERESTING_TAGS = 
  set("A","FORM","INPUT","SCRIPT","OBJECT");


совсем нечитабелен. Какой тут Set: HashSet? TreeSet? UnmodifiableSet? А почему метод set выделен только для HashSet? Автор только один тип set'а использует?

3. Далее, static import — это зло, так как из предыдущего кода можно подумать, что set — это метод текущего класса. Ну и везде в статье, якобы, static import уменьшает кол-во кода, а значит увеличивает читаемость. Это не так.

4. В коде

Map<String,Integer> WEIGHTS = zipMap(
  ar("bad", "poor", "average", "nice", "outstanding"),
  ar(-2,    -1,     0,         1,      3));


есть один недостаток: после форматирования получается

Map<String, Integer> WEIGHTS = zipMap(
        ar("bad", "poor", "average", "nice", "outstanding"),
        ar(-2, -1, 0, 1, 3));


согласитеть, уже не очевидно, что кол-во ключей равно кол-во значений, а это рано или поздно приведет к RuntimeException.

5. Кое что в статье боян. Например код

public class CollectionFactory 
{
  public static <K,V> Map<K,V> newMap() 
  {
   return new HashMap<K,V>();
  }
}


уже был более года назад был написан в Google Collections:

package com.google.common.collect;

public final class Maps {
  public static <K, V> HashMap<K, V> newHashMap() {
    return new HashMap<K, V>();
  }

  public static <K, V> LinkedHashMap<K, V> newLinkedHashMap() {
    return new LinkedHashMap<K, V>();
  }

  public static <K extends Comparable, V> TreeMap<K, V> newTreeMap() {
    return new TreeMap<K, V>();
  }
}


5. Я согласен с jkff, что главное это бизнес требования. Все остальное сделает IDE: сгенерит, подставит, заимпортирует ну, и Apache Commons или Google Collections, кому нравится, помогают. Нам, java-программистам, можно не заморачиваться на синтаксический сахар
Re[2]: Приемы программирования на Java
От: Baudolino  
Дата: 24.08.09 19:57
Оценка: +2
_> ...Например, класс
_>
_>public abstract class Filters 
_>{
_>  public static Filter and(Filter a, Filter b) {return new AndFilter(a,b);}
_>}
_>

_>совершенно бесполезен, если он решает только проблему якобы "плохочитаемого кода" типа
_>
_>Filter f = new AndFilter(first, second);
_>

Вы внезапно забыли, что фильтры комбинируются и запись and(or(f1,f2),not(f3)) все же компактнее и проще для восприятия, чем куча конструкторов.

_>2. На мой взгляд, главное, чтобы код читался хорошо, хотя бы теми кто его пишет. Например, код

_>
_>private static final Set<String> INTERESTING_TAGS = 
_>  set("A","FORM","INPUT","SCRIPT","OBJECT");
_>

_>совсем нечитабелен.
Очень даже читабелен. Надо понимать, что автор показал направление (о чем там явно сказано), а не взял на себя труд реализовывать идеальную библиотеку. В данном случае может быть например constSet(...).
_>А почему метод set выделен только для HashSet? Автор только один тип set'а использует?
Обзовите его hashSet или newHashSet как в Google Collections, если вам это важно. Но конкретная реализация структуры далеко не всегда важна, поэтому можно выбрать и более компактную запись.

_>3. Далее, static import — это зло, так как из предыдущего кода можно подумать, что set — это метод текущего класса. Ну и везде в статье, якобы, static import уменьшает кол-во кода, а значит увеличивает читаемость. Это не так.

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

_>5. Кое что в статье боян.

Ну, положим, текст статьи в ЖЖ я видел больше, чем год назад. Прежде чем что-либо назвать баяном, обратите внимание на дату материала появления в первоисточнике. Да и не важно это всё.

_>Нам, java-программистам, можно не заморачиваться на синтаксический сахар

Не знаю как вам, java-программистам, а нам, java-программистам, можно и заморочиться.
Re[2]: Приемы программирования на Java
От: elmal  
Дата: 25.08.09 05:02
Оценка:
Здравствуйте, DenLion, Вы писали:

DL>читаемость "обычного стиля" (someMap.put(CONSTANT_WITH_LONG_NAME, "anotherStringConstant")) будет

DL>выше. При попытке перевести эту громадину на предлагаемый вами стиль получится страшная каша.
Я делаю так:

Map map = CollectionUtils.map(mapEntry(CONSTANT_WITH_LONG_NAME,  "anotherStringConstant"),
                              mapEntry(CONSTANT_WITH_LONG_NAME1, "anotherStringConstant1"),
                              mapEntry(CONSTANT_WITH_LONG_NAME2, "anotherStringConstant2"),
                              mapEntry(CONSTANT_WITH_LONG_NAME3, "anotherStringConstant3"));

Это я к тому, что всегда можно улучшить то, что предлагают другие. А статья неплохая, я многими способами стал пользоваться. Очень было б неплохо, чтоб хотя бы 20% задумывались бы о стиле, послоянно думая, как можно написать лучше.
Re[3]: Приемы программирования на Java
От: mazurkin http://mazurkin.info
Дата: 25.08.09 05:36
Оценка:
elmal wrote:
>
> Map map = CollectionUtils.map(mapEntry(CONSTANT_WITH_LONG_NAME,  "anotherStringConstant"),
>                               mapEntry(CONSTANT_WITH_LONG_NAME1, "anotherStringConstant1"),
>                               mapEntry(CONSTANT_WITH_LONG_NAME2, "anotherStringConstant2"),
>                               mapEntry(CONSTANT_WITH_LONG_NAME3, "anotherStringConstant3"));
>

> Это я к тому, что всегда можно улучшить то, что предлагают другие.

Во-первых, мой мозг отказывается понимать: чем всех вас не устраивает
стандартный стиль? Вот я не вижу никаких преимуществ в ваших конструкциях...

Map<A,B> map = new HashMap<A,B>();
map.put(CONSTANT_WITH_LONG_NAME,  "anotherStringConstant");
map.put(CONSTANT_WITH_LONG_NAME1, "anotherStringConstant1");
map.put(CONSTANT_WITH_LONG_NAME2, "anotherStringConstant2");
map.put(CONSTANT_WITH_LONG_NAME3, "anotherStringConstant3");


Во-вторых, лично я выношу подобные константные мэпы либо во внешние
properties-файлы, либо делаю инжекцию через IoC-контейнер спринга.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: Приемы программирования на Java
От: elmal  
Дата: 25.08.09 05:58
Оценка:
Здравствуйте, mazurkin, Вы писали:

M>Во-первых, мой мозг отказывается понимать: чем всех вас не устраивает

M>стандартный стиль? Вот я не вижу никаких преимуществ в ваших конструкциях...
Мапы часто используются статические. Соответственно такой записью я избавляюсь от static секции. Во вторых, в случае, если я инициализирую список подобным образом, у меня сразу видно количество элементов, и я могу при создании списка просетать это значение — мелочь, а приятно. Тоже самое с мапкой, если мне надо будет реализовывать BycicleMap, то я смогу использовать эту информацию, и нахаляву получить достаточно оптимальную реализацию.

M>Во-вторых, лично я выношу подобные константные мэпы либо во внешние

M>properties-файлы, либо делаю инжекцию через IoC-контейнер спринга.
Очень плохо читается во первых. Во вторых, компилятор корректность этих пропертей не сможет проверить. Сложности с рефакторингом (да, я знаю что у большинства рефакторинг не в почете). В третьих, часто константы мапишь на обработчик, соответственно проперти не катят. Относительно спринга — одновременно и плохо читается, и плохо поддерживается. spring очень хорошая штука, вот только употреблять ее надо к месту, а не городить километровые XML в которых сам черт ногу сломит, и пытаясь вообще все запихнуть в XML.

PS Избавившись от логики непосредственно в спринговой конфигурации удалось время разработки уменьшить раз в 10 по сравнению с теми, кто на XML молился. Более того, протестировать удалось лучше, багов вообще не оказалось
Re[4]: Приемы программирования на Java
От: komaz Россия  
Дата: 25.08.09 06:08
Оценка:
Здравствуйте, mazurkin, Вы писали:

M>elmal wrote:

>>
>> Map map = CollectionUtils.map(mapEntry(CONSTANT_WITH_LONG_NAME,  "anotherStringConstant"),
>>                               mapEntry(CONSTANT_WITH_LONG_NAME1, "anotherStringConstant1"),
>>                               mapEntry(CONSTANT_WITH_LONG_NAME2, "anotherStringConstant2"),
>>                               mapEntry(CONSTANT_WITH_LONG_NAME3, "anotherStringConstant3"));
>>

>> Это я к тому, что всегда можно улучшить то, что предлагают другие.

M>Во-первых, мой мозг отказывается понимать: чем всех вас не устраивает

M>стандартный стиль? Вот я не вижу никаких преимуществ в ваших конструкциях...

M>
M>Map<A,B> map = new HashMap<A,B>();
M>map.put(CONSTANT_WITH_LONG_NAME,  "anotherStringConstant");
M>map.put(CONSTANT_WITH_LONG_NAME1, "anotherStringConstant1");
M>map.put(CONSTANT_WITH_LONG_NAME2, "anotherStringConstant2");
M>map.put(CONSTANT_WITH_LONG_NAME3, "anotherStringConstant3");
M>


M>Во-вторых, лично я выношу подобные константные мэпы либо во внешние

M>properties-файлы, либо делаю инжекцию через IoC-контейнер спринга.

Как минимум — в первом случае это можно засунуть прям в инициализацию члена класса. После этого откуда угодно сделав Open declaration в IDE видим инициализацию. Во втором случае код придется класть в static {} блок (или в конструктор для нестатичных членов)
Re[5]: Приемы программирования на Java
От: mazurkin http://mazurkin.info
Дата: 25.08.09 06:13
Оценка: +1
elmal wrote:

> Мапы часто используются статические. Соответственно такой записью я

> избавляюсь от static секции. Во вторых, в случае, если я
> инициализирую список подобным образом, у меня сразу видно количество
> элементов, и я могу при создании списка просетать это значение -
> мелочь, а приятно. Тоже самое с мапкой, если мне надо будет
> реализовывать BycicleMap, то я смогу использовать эту информацию, и
> нахаляву получить достаточно оптимальную реализацию.

.... и тут же создаете N совершенно ненужных инстансов классов через
mapEntry

Насчет статической секции — я тоже не люблю статические секции. Поэтому
возможно создал бы мэпу с настройками отдельным синглтоном и использовал
бы ее.

> Очень плохо читается во первых. Во вторых, компилятор корректность

> этих пропертей не сможет проверить. Сложности с рефакторингом (да, я
> знаю что у большинства рефакторинг не в почете). В третьих, часто
> константы мапишь на обработчик, соответственно проперти не катят.
> Относительно спринга — одновременно и плохо читается, и плохо
> поддерживается. spring очень хорошая штука, вот только употреблять ее
> надо к месту, а не городить километровые XML в которых сам черт ногу
> сломит, и пытаясь вообще все запихнуть в XML.

Сложностей с рефакторингом отсутствуют как класс — по крайней мере в
IDEA. Насчет корректности тоже не понял — любой тест, поднимающий
контекст сразу выявит все ошибки.

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

> PS Избавившись от логики непосредственно в спринговой конфигурации

> удалось время разработки уменьшить раз в 10 по сравнению с теми, кто
> на XML молился. Более того, протестировать удалось лучше, багов
> вообще не оказалось

Мне кажется вы сильно сейчас приукрасили все — у вас XML-фобия просто

Не надо молиться на XML — вынос конфигурации в IoC уменьшает сцепление
между классами и увеличивает связность внутри классов, что отражается
однозначно положительным образом на качестве кода и общей архитектуре. А
абстрактные баги лечатся совершенно конкретными тестами.
Posted via RSDN NNTP Server 2.1 beta
Re[5]: Приемы программирования на Java
От: mazurkin http://mazurkin.info
Дата: 25.08.09 07:05
Оценка:
komaz wrote:

> Во втором случае код придется класть в static {} блок (или в конструктор для нестатичных членов)


Вы все — статикофобы!

Вот вам псевдо-функциональный инициализатор...

import java.util.HashMap;
import java.util.Map;

public final class MapComposer<K,V> {

    private Map<K, V> map;

    private MapComposer(Map<K, V> map) {
        this.map = map;
    }

    public static <K,V> MapComposer<K,V> init(Map<K,V> map) {
        return new MapComposer<K,V>(map);
    }

    public static <K,V> MapComposer<K,V> initHashMap(Class<K> k,
Class<V> v) {
        return new MapComposer<K,V>(new HashMap<K,V>());
    }

    public Map<K, V> map() {
        return map;
    }

    public MapComposer<K,V> entry(K key, V value) {
        map.put(key, value);
        return this;
    }

}


import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class Application {

    private Map<Integer, Long> map1 =
            MapComposer.initHashMap(Integer.class, Long.class).
            entry(1, 20L).
            entry(2, 30L).
            entry(3, 40L).
            map();

    private Map<String, Date> map2 =
            MapComposer.init(new HashMap<String, Date>()).
            entry("1", new Date(1)).
            entry("2", new Date(2)).
            entry("3", new Date(3)).
            map();

    public static void main(String[] args) throws Exception {
        Application application = new Application();
    }
}
Posted via RSDN NNTP Server 2.1 beta
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.