Здравствуйте, Blazkowicz, Вы писали:
T>>А то в Java параметризировать методы нельзя. B>Можно.
Статические, как я понял, нельзя. Или приведи пример, какой код будет компилироваться, пожалуйста.
Здравствуйте, techgl, Вы писали:
T>>>А то в Java параметризировать методы нельзя. B>>Можно. T>Статические, как я понял, нельзя. Или приведи пример, какой код будет компилироваться, пожалуйста.
public <T> Set<T> set(T... ts) {
return new HashSet<T>(Arrays.asList(ts));
}
Там как раз пропущен указатель на то что метод Generic.
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));
}
Очень интересная статья, спасибо. Но есть одно некоторые ньюансы: у нас в проекте есть блок статической
инициализации мапа из более чем 4ёх десятков строк для пары ключ->значение, где каждый
ключ и каждое значение есть стринг из более чем 30ти (до 50ти) символов. В таком случае, мне кажется,
читаемость "обычного стиля" (someMap.put(CONSTANT_WITH_LONG_NAME, "anotherStringConstant")) будет
выше. При попытке перевести эту громадину на предлагаемый вами стиль получится страшная каша.
Вставлю свои 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 уменьшает кол-во кода, а значит увеличивает читаемость. Это не так.
согласитеть, уже не очевидно, что кол-во ключей равно кол-во значений, а это рано или поздно приведет к 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-программистам, можно не заморачиваться на синтаксический сахар
_>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-программистам, можно и заморочиться.
Здравствуйте, DenLion, Вы писали:
DL>читаемость "обычного стиля" (someMap.put(CONSTANT_WITH_LONG_NAME, "anotherStringConstant")) будет DL>выше. При попытке перевести эту громадину на предлагаемый вами стиль получится страшная каша.
Я делаю так:
Это я к тому, что всегда можно улучшить то, что предлагают другие. А статья неплохая, я многими способами стал пользоваться. Очень было б неплохо, чтоб хотя бы 20% задумывались бы о стиле, послоянно думая, как можно написать лучше.
Здравствуйте, mazurkin, Вы писали:
M>Во-первых, мой мозг отказывается понимать: чем всех вас не устраивает M>стандартный стиль? Вот я не вижу никаких преимуществ в ваших конструкциях...
Мапы часто используются статические. Соответственно такой записью я избавляюсь от static секции. Во вторых, в случае, если я инициализирую список подобным образом, у меня сразу видно количество элементов, и я могу при создании списка просетать это значение — мелочь, а приятно. Тоже самое с мапкой, если мне надо будет реализовывать BycicleMap, то я смогу использовать эту информацию, и нахаляву получить достаточно оптимальную реализацию.
M>Во-вторых, лично я выношу подобные константные мэпы либо во внешние M>properties-файлы, либо делаю инжекцию через IoC-контейнер спринга.
Очень плохо читается во первых. Во вторых, компилятор корректность этих пропертей не сможет проверить. Сложности с рефакторингом (да, я знаю что у большинства рефакторинг не в почете). В третьих, часто константы мапишь на обработчик, соответственно проперти не катят. Относительно спринга — одновременно и плохо читается, и плохо поддерживается. spring очень хорошая штука, вот только употреблять ее надо к месту, а не городить километровые XML в которых сам черт ногу сломит, и пытаясь вообще все запихнуть в XML.
PS Избавившись от логики непосредственно в спринговой конфигурации удалось время разработки уменьшить раз в 10 по сравнению с теми, кто на XML молился. Более того, протестировать удалось лучше, багов вообще не оказалось
>> Это я к тому, что всегда можно улучшить то, что предлагают другие.
M>Во-первых, мой мозг отказывается понимать: чем всех вас не устраивает M>стандартный стиль? Вот я не вижу никаких преимуществ в ваших конструкциях...
M>
M>Во-вторых, лично я выношу подобные константные мэпы либо во внешние M>properties-файлы, либо делаю инжекцию через IoC-контейнер спринга.
Как минимум — в первом случае это можно засунуть прям в инициализацию члена класса. После этого откуда угодно сделав Open declaration в IDE видим инициализацию. Во втором случае код придется класть в static {} блок (или в конструктор для нестатичных членов)
elmal wrote:
> Мапы часто используются статические. Соответственно такой записью я > избавляюсь от static секции. Во вторых, в случае, если я > инициализирую список подобным образом, у меня сразу видно количество > элементов, и я могу при создании списка просетать это значение - > мелочь, а приятно. Тоже самое с мапкой, если мне надо будет > реализовывать BycicleMap, то я смогу использовать эту информацию, и > нахаляву получить достаточно оптимальную реализацию.
.... и тут же создаете N совершенно ненужных инстансов классов через
mapEntry
Насчет статической секции — я тоже не люблю статические секции. Поэтому
возможно создал бы мэпу с настройками отдельным синглтоном и использовал
бы ее.
> Очень плохо читается во первых. Во вторых, компилятор корректность > этих пропертей не сможет проверить. Сложности с рефакторингом (да, я > знаю что у большинства рефакторинг не в почете). В третьих, часто > константы мапишь на обработчик, соответственно проперти не катят. > Относительно спринга — одновременно и плохо читается, и плохо > поддерживается. spring очень хорошая штука, вот только употреблять ее > надо к месту, а не городить километровые XML в которых сам черт ногу > сломит, и пытаясь вообще все запихнуть в XML.
Сложностей с рефакторингом отсутствуют как класс — по крайней мере в
IDEA. Насчет корректности тоже не понял — любой тест, поднимающий
контекст сразу выявит все ошибки.
Насчет того, что плохо читается — немногим более чем полностью уверен,
что в данном конкретном случае это вопрос очень субъективный — в вашем,
варианте знаете ли тоже читаемость не сахар — тут вам не Питон.
> PS Избавившись от логики непосредственно в спринговой конфигурации > удалось время разработки уменьшить раз в 10 по сравнению с теми, кто > на XML молился. Более того, протестировать удалось лучше, багов > вообще не оказалось
Мне кажется вы сильно сейчас приукрасили все — у вас XML-фобия просто
Не надо молиться на XML — вынос конфигурации в IoC уменьшает сцепление
между классами и увеличивает связность внутри классов, что отражается
однозначно положительным образом на качестве кода и общей архитектуре. А
абстрактные баги лечатся совершенно конкретными тестами.