2013-09-20

Гипертекстовый код на Java

В любой уважающей себя IDE есть ctrl+click-to-go, когда можно щелкнуть на переменной и перейти к объявлению, щелкнув на методе - перейти в его реализацию, щелкнув на классе перейти в это класс. Тривиальнейшая и очевиднейшая вещь воспринимается как должное, пока не сядешь за какой-нибудь Visual Studio Express, где её почему-то нет поправка: в VS есть F12 (Eclipse и NetBeans это умеют, но зачем ездить на жигулях, если есть бесплатный кадиллак). Но мы не будем рассматривать отщепенцев.

Зачастую положительные изменения не происходят, пока не преодолен некий болевой порог. Неудобство воспринимается как должное. Когда наконец происходит СУКАБЛЯЗАЕБАЛОАЖБЕСИТ начинаешь что-то думать. Наступает эдакий момент откровения.

@see

В контексте поста впервые у меня это произошло при дебаге шины событий в org.vaadin.mvp. Вот описание принципа на примере гугловой Гуавы. Вкратце: есть шина в виде интерфейса, на методы которого через аннотацию навешаны классы-подписчики получающие уведомления о событиях. Единственная проблема: если метод в шине называется fooEvent(Bar bar), то в подписчике этот метод должен называться onFooEvent(Bar bar). Поскольку в шине указаны конкретные классы то можно click-to-go и перейти в класс, ладно уж не на конкретный метод. А вот назад перейти нельзя - и этот односторонний тоннель реально начинает накалять, когда хочется прыгнуть назад и перейти в другого подписчика.

Решение очень простое: добавить @see или {@link} на шину, чтобы в одно нажатие вернуться назад. Со временем код начинает обрастать такими тоннелями: нужно быстро подсмотреть пример реализации - {@link}, нужна ссыка на спецификацию - <a href>. Мгновенная телепортация в нужно место это круто. Сегодня поймал себя на том, что поставил ссылку внутри одного файла: фрагмент кода находился не там где я его ожидал увидеть. Перед методом, кстати было пояснение, какого, собственно, хрена он находится не там где ему положено быть - очень полезное требование обязательного пояснения неочевидных решений, чтобы кто-нибудь не попытался с наскоку чинить. Так сразу понятно: человек так сделал отдавая себе отчет в том что он делает. В общем поставил ссылку на метод в то место, где по-умолчанию будут его искать.

@deprecated

Джавадоки вообще полезнейшая штука. На втором месте после линков у меня стоит аннотация @Deprecated и одноименный тег в джавадоке. В исходнике классы, методы, переменные будет зачеркнуты, что само по себе должно вызвать сомнения в целесообразности их использования. Хорошим тоном является в джавадоке пояснить - почему это не рекомендуется применять и что использовать вместо. Иногда как deprecated помечаются внутренние методы, которые почему-то не были сделаны приватными.

В том же mvp есть FactoryPresenter с переменной, которую по-задумке должны использовать потомки. К сожалению, после изменения логики, это переменной стало нельзя пользоваться. Но как защититься от случайного использования? Добавить в наследнике переменную, хоторая перекроет родительскую и пометить её как deprecated:

    /** @deprecated never use this field and do not delete this warning, use getPresenterFactory() instead */
    @Deprecated
    @SuppressWarnings("unused")
    protected OrangeucePresenterFactory presenterFactory = null;


Как же приятно читать такие послания из прошлого - прям чувствуешь, как пара строк экономит уйму времени на борьбу с вотзефаком.