Search
Write a publication
Pull to refresh

Comments 15

Я бы тоже сопротивлялся. Главная проблема с такой аннотацией — это иллюзия читабельности. Если я каждый день с этим не сталкиваюсь (а Юнг и его товарищ, видимо, не сталкиваются), то мне не будет понятно, что происходит, особенно в случае с @Cleanup(«free»). Здравствуй, рефлексия! Отдельный луч ненависти авторам за это. Та самая ситуация, когда абстракция протекла и вместо отказа от неё начали городить костыли.

В общем, удобство это очень субъективное и условное. Особенно, если речь идёт об изменениях в compile time. Действительно, как дебажить потом? Я бы пошёл по пути версии 2 + обёртки.

Мне всегда казалось, что Lombok срабатывает во время сборки кода. Я не прав?
Дебажить — поставить два бряка, один на код, второй на метод free. Зачем дебажить то, что происходит внутри finally? Я все-таки надеюсь, что люди, пишущие Lombok умные, и сделали там все правильно.
Никакой рефлексии. Lombok во время компиляции преобразует
@Cleanup("free")
в try-finally с вызовом метода free. А если такого метода нет, то возникнет ошибка компиляции. Да и плагин Lombok-а к IDEA (или к Eclipse) во время написания кода подскажет, что такого метода нет.
Lombok это не рефлексия, а расширение языка через annotation processors.
Насколько я помню (правда, пользовался только для других методов), в Idea есть кнопка «Delombok», которая превращает аннотации в скрывающийся за ними код. Вот ее и использовать при дебаге.
Да тут не надо использовать delombok для дебага) Зачем дебажить то, что в finally-блоке? Сам код надо дебажить и free.

Код очень конкретный в силу перегруженности прямым управлением ресурсами.
Его логично разбить на методы (или классы) для получения, преобразование и записи данных, каждый из которых использует только те соединения, запросы и парсеры, какие нужны ему самому.
Конкретные фабрики ресурсов передавать из точки сборки.
Короче, использовать DI и будет вам счастье.
И да, возможности Java 8 смотрятся намного лучше магических аннотаций, совершенно непонятно, что там такого ужасного для автора.

Ужасного там то, что он работает только на Java 8, а также то, что появляется какая-то магическая переменная fake, которая используется только для того, чтобы выполнить код очистки ресурсов, и вот это как раз-таки на первый взгляд не очевидно
Ужасного там то, что он работает только на Java 8

Если у проекта нет требования совместимости с ранними версиями, то какая разница?


появляется какая-то магическая переменная fake

Это не магия, а полноценная часть языка. И ответственность данной переменной простая и понятная — дать возможность очистки для объекта, которые не умеет делать это самостоятельно. Хотя, конечно, приятнее было бы оставить просто выражение.


А вот специальные атрибуты, повязанные на конкретную библиотеку — самая что ни на есть магия со всеми вытекающими.

В данном случае единственным бескостыльным методом является:
try {
  ... открывает ресурс ...
} finally {
  ... правильно закрываем ресурс, если он не null ...
}

Все остальные варианты — это костыли (за исключением обертки, но ее писать не удобно). И @Cleanup — это аннотация, которая помогает сделать более менее красивый костыль. Переменная fake и использование передачи метода, чтобы только закрыть ресурс — она просто ужасна:
Resource res; // вот тут она объявляется только потому, что внутри try ее не объявить - это жесть №1
try (Autoclose fake = (res = ResourceCreator.create())::free) { // все, fakе больше нигде не используется, это жесть №2
  ... тут уже полезный код ...
}

Я же не говорю, что давайте использовать @Cleanup везде, нет. Если метод маленький и там один такой ресурс с free, то не беда, давайте просто try-finally сделаем. Но когда идет работа с потоками, один вкладывается в другой, разные врайтеры, которые не закрывают ресурсы, когда закрываются сами, и если их много, то почему нет? Имхо одна строчка
@Cleanup("free") Resource = ...

куда понятнее и более читаемая.
В данном случае единственным бескостыльным методом является

Вы считаете бескостыльным только явное?
Здесь с вами многие не согласятся.
Лично я полагаю, что шаблонный код должен быть как можно меньше. Это позволяет при чтении сосредоточиться на реализованном алгоритме вместо шума.


Переменная fake и использование передачи метода, чтобы только закрыть ресурс — она просто ужасна

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


Что до использования передачи метода — это заведомо лучше атрибута со строковым параметром.

  1. Я тоже за использование шаблонного кода как можно меньше.
  2. Ничего плохого в строкового имени метода для этапа компиляции нет.
  3. Приведите код шаблонной обертки.
Ничего плохого в строкового имени метода для этапа компиляции нет.

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


Приведите код шаблонной обертки

Не вопрос


import java.lang.*;
import java.util.function.Function;

public final class Usable<T> implements AutoCloseable
{
    public Usable(T object, Function<T, AutoCloseable> toCloseable)
    {
        _object = object;
        _closeable = toCloseable.apply(object);
    }

    public static <T> Usable from(T object, Function<T, AutoCloseable> toCloseable)
    {
        return new Usable<T>(object, toCloseable);
    }

    public T getObject()
    {
        return _object;
    }

    public void close() throws Exception
    {
        _closeable.close();
    }

    private AutoCloseable _closeable;

    private T _object;
}

Прошу извинить если коряво — я на яве не пишу совсем, по ссылке онлайн-демка.

сейчас все поделилось на тех, кто пишет на Java и тех, кто пишет на Lombok
UFO landed and left these words here
Sign up to leave a comment.

Articles