Как стать автором
Обновить

Комментарии 44

Несколько дней.
Я хотел когда-то доработать что-то в hibernate, чтобы не писать лишнего при коннекте к firebird. Тогда у них был SVN а патчи надо было слать почтой. Отослал. 2 строки.
Тот проект мой заглох, больше я с firebird не работал.
Через 7 карт мне пришёл ответ, мол надо ж pull-request в github присылать. А я уже забыл, что и зачем делал…

7 лет, конечно…

Солидно! 7 лет
Считаю, что нужно отличать дебаг и последующий фикс и новую функциональность.
Для первого две строчки за пару дней — это отличный результат. Хуже, когда на это уходит месяц.
А вот новый функционал пишется гораздо проще и веселее, и быстрее (если уж считать в SLOC).
Согласен. Ещё рефакторинг — источник нового кода, почти как новая фича
У нас был джун, он говорил на стендапах что-то вроде: «Я вчера рефакторил Редактор»
Это означало, что он запилил пару новых фич в Редактор и ничего не рефакторил.
Ещё гораздо меньше строк пишется/генерируется IDE, если подключить к проекту lombok
Или Kotlin…
Хотя в Kotlin (и Scala) пока нет удобных для Java аннотаций для логгирования
@Log
@Slf4j
@Log4j
@Log4j2
Или groovy)

зачем аннотация, когда есть kotlin-logging

Потому что в Lombok используется аннотация? :) Искал решение похожее на то, что уже использовал.
Такой код:
companion object: KLogging()

выглядит длиннее чем одна коротка аннотация но лучше чем обычно.
val logger = LoggerFactory.getLogger("class name")

А чем плох такой вариант?


val Any.logger: Logger by object : ReadOnlyProperty<Any, Logger> {
    val loggers = ConcurrentHashMap<Class<*>, Logger>()
    override fun getValue(thisRef: Any, property: KProperty<*>): Logger {
        return loggers.computeIfAbsent(thisRef.javaClass, LoggerFactory::getLogger)
    }
}

Да, не static final, но неужели не пофиг?

Вопрос в лаконичности.
Еще раз: в Lombok для создания объекта логгера используется одна короткая анннотация. В Kotlin это выглядит многословней. Вот вся претензия.

экономия на спичках

Так наоборот же. Эту штуку надо написать всего один раз (и можно даже в библиотеке) и всё! Вам больше вообще ничего делать не надо. У всех классов уже есть логгер. В отличии от ломбока, в котором как раз надо еще целую аннотацию поставить.
Моя тупить. Можно пример минипроекта на plain Kotlin (не Android, spring, webservices, буквально три-четыре простеньких класса) который работает с этим?
Если честно, то лень. Но это и есть весь код. Суете в либу на топ уровне что я писал ранее, а используется просто как
import org.dou.lib.logger

class Foo {
    init {
        logger.info("hello") //[main] INFO org.dou.Foo - hello
    }
}


На самом деле, я уже обнаружил две большие проблемы у этого варианта:
1. Это публичное экстеншн проперти, так что я «logger» могу написать не только внутри класса, но и снаружи
42.logger.info("msg") //[main] INFO java.lang.Integer - msg

2. Он вообще не работает с топ левел функциями (вне класса/объекта). Т.к. там нет this, у которого logger и отрастает.

В принципе, обе проблемы решаются если убрать «Any.» и сделать просто
val logger: Logger get() { TODO() }
(тоже на рутовом уровне), но здесь я пока не придумал как в теле геттера получать класс, откуда он вызывается. Каждый раз через исключение смотреть стектрейс — явно плохо.
Ну да, иначе никак не получается сейчас
val public_strange_name_do_not_use_it = ConcurrentHashMap<String, Logger>()

inline val logger: Logger
    get() {
        return public_strange_name_do_not_use_it.computeIfAbsent(Exception().stackTrace[0].className) { cn -> LoggerFactory.getLogger(Class.forName(cn)) }
    }


По получаемому синтаксису вроде идеально получается, здесь только с перформансом уже проблемы скорее всего будут (по крайней мере, для библиотечной функции общего пользование такое явно недопустимо). В принципе, если дождаться JEP-303, то в паре с инлайном это будет идеальное решение. По идее, тогда даже мапа будет не нужна, т.к. можно будет повесить CallSite напрямую на нужный логгер, но в этом я пока не уверен, надо внимательнее посмотреть.
Во!
    public static CallSite bootstrapLoggerFactory(MethodHandles.Lookup lookup, String name, MethodType type) {
        Logger logger = LoggerFactory.getLogger(lookup.lookupClass());
        MethodHandle mh = MethodHandles.constant(Logger.class, logger);
        return new ConstantCallSite(mh);
    }
А, блин, лоханулся я. Это же фича джава компилятора будет, так что надо еще допиливать котлиновский чтобы он про Intrinsics.invokedynamic тоже узнал. А если в любом случае надо его пилить, то и JEP-303 уже можно не ждать и сделать свой велосипед.

Когда новую функциональность надо вкорячить в существующий код – это тоже не всегда тривиально бывает.

Зависит от дизайна и техдолга существующего кода…
Была ошибка в 1 символ (другая кавычка в JSON файле на стороне сервера)

1) создать стори в JIRA
2) создать бранч в git server project
3) создать бранч в git front project
4) исправить кавычку в server
5) добавить тест в front
6) прогнать все тесты
7) pull request
8) merge 1
9) merge 2
10) close story

Неделя. А фактической работы — 0.3 секунды.

И да — ту кавычку вставил MAC OS текстпад родной
Неделя на символ — это позабористее строчек!
Когда «процессы» побеждают здравый смысл :(

Не очень понял, почему фикс делаем в "server project" а тест пишем во "front project". Было бы в одном месте, число действий сократилось бы вдвое.

UI Test на стороне телефона, который читает данные с сервера.

Все равно неясно.


Если сервер возвращает JSON, который ломает клиента, то нужно либо пофиксить сервер (и написать в сервере тест "не должен возвращать плохой json"), либо научить клиента обрабатывать такую ситуацию (и написать в клиенте тест "не падать когда получил такой-то json").

Спасибо, интересно. Согласен с автором что race condition сложно воспроизвести
Легко может. Особенно при программировании для встраиваемых систем, да ещё в случае многопроцессорных устройств! Когда аппаратные глюки накладываются на программные, причём в другом микроконтроллере.
Браво! Это вообще отдельная область разработки. Наводки, зависания из-за непропайки
Чего только не случается. Непропайки, гонки фронтов. Последний раз провозился две недели потому что у микросхемы уважаемого производителя ADI почему то при понижении напряжения питания надо увеличивать время между записями в два регистра с миллисекунд буквально до 10 секунд. Без этого она не просто блокировала шину SPI и почему то начинала потреблять раз в 10 больше чем положено. В результате начинал греться стабилизатор и срабатывала тепловая защита. Попробуй разберись где там причина а где следствие.
Но на хабре почему то программистов микроконтроллеров не считают разработчиками вообще, нас даже изгоняли с этой площадки года на два или три в недалёком прошлом.
Наверно потому, что приравняли нас к ШАМАНАМ
Угу, знакомо. Отладка кода осциллографом, отладка железа при помощи GDB… Правка бага в коде при помощи проводочка, правка ошибки в разводке кодом…

Причем даже на довольно больших компах замашки embeded работают. Как понять, на какой скорости и в каком формате программа гонит данные по COM-порту? Берем осциллограф и смотрим… Это вот вчера было, когда некий древний linux при воде русских символов переключил формат консоли из 8N1 в 7N1. :-) Первая мысль — а давайте осциллографом глянем.
Видимо разработка специфичнее и требует большего количества знаний, документации больше, многое ценное под NDA и комьюнити меньше.
Одна строчка
int x

Съела отпуск. Убила сорсник.
Когда-нибудь я допишу статью об этом…
Интрига!
Перекрытие имени в объемлющей области видимости? Бывает. Поэтому стоит включить соответствующую опцию в компиляторе.
Если быть точным — сознательное перекрытие областей, как хак решивший кучу проблем. Всё сломалось, когда гуру клинкода эту строчку удалил (она специально была написана в модуле где не используется).
Если это и решало кучу проблем, в конечном итоге такое хрупкое решение вряд ли можно признать хорошим. Поэтому не стоит винить «гуру клинкода», если только этот int x не был помечен очевидным и подробным комментарием.
//Do NOT touch! Very Important Code:
int x 

Позже пришлось добавить ещё и простыню текста снизу, поясняющую цель существования данного хака.
Комментарий понятный, но не подробный, поэтому был больше похож на шутку. Очень важный код, серьёзно? Возможно, была бы та простыня текста там раньше, и не пришлось бы разгребать проблемы.
Наверное, со своими пятью копейками про три дня ковыряния в коде DevExpress во время поиска причин непонятного поведения компонента WinForms после выхода новой версии с отсутствием документации по изменению этого поведения не стоит писать, потому что блог про OpenSource и Java? :)
Почему же… Боль-то одна — красноглазие. Не мне одному будет интересно.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории