Pull to refresh
39
0
Борис Ванин @fogone

Пользователь

Send message
не совсем понимаю, если это данные которые параметризируют выполнение метода, то почему тогда его не передать в качестве параметра? это по крайней мере не будет создавать иллюзию и будет добавлять чистоты методу в функциональном смысле. И как вызывающий поймет, что ему необходимо передать какой-то контекст? Для этого обычно используется явно объявление параметров метода, которые гарантирют заодно, что его без этих параметров не вызовешь на этапе компиляции еще. А так получается, что вроде всех перехитрили: и компилятор и вызывающего этот метод заодно.
Но нужно для этого всего найти какое-то реальное применение.
Сначала напедалить, а потом думать зачем — всегда так делаю.
Можно хранить в этом контексте всё, что угодно.
Это очень полезный горшок.

Это я к тому, что не совсем понятно, какую именно проблему мы решаем. Если всё это только ради того, чтобы вынести логирование из сервисного метода, то сложно себе представить, что оно того стоит. А если передавать какую-то значимую информацию в этом контексте, то это резко увеличивает неявную связанность между сервисами и лично я бы старался такого избегать до того момента, пока другого варианта просто нет. Можно себе представить, что мы хотим например закешировать полученные из бд сущности, чтобы увеличить производительность, но такой ценой я бы делал это в последнюю очередь.
Большинство Java веб-серверов создают новый поток выполнения для каждого поступающего запроса, и уже в этом потоке в конце концов вызывают функцию, которую написали вы, разработчик приложения.

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

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

Большинство приложений, веб- и прочих, их не используют, но они хотя бы есть. Некоторые Java веб-серверы пытаются как-то применять преимущества неблокирующих вызовов, однако подавляющее большинство развёрнутых Java-приложений всё ещё работает так, как описано выше.

Не знаю ни одного современного веб-сервера на джаве, который бы не использовал неблокирующее io и ивент-луп так или иначе. И да, как описано выше соответственно сейчас никто не работает, кроме может быть каких-то самопальных поделок сделанных людьми, которые прочли статьи вроде этой.

Прежде чем перейти к обсуждению Go, должен сообщить, что я его поклонник.

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

Нужны колбэки

Нет, у джавы для неблокирющего io есть каналы из nio, которые прекрасно работают без колбэков и позволяют эффективно реализовать ивентлуп.

Бенчмарки вообще уморили: какие-то дефолтные конфиги и jsp для обработки запроса. Выбраны почему-то именно сервлеты, запускаются «бэнчмарки» без прогрева; когда один раз запускалось, томкат за указанное время еще и жсп поди успел скомпилировать. От реализации рассчета хеша вообще слезы на глаза наворачиваются. Не буду ничего говорить про другие языки, уверен, что там так же ляп на ляпе. А ведь кто-то возможно посмотрит и сделает какой-то вывод далекий от реальности.
Вот что-то на счёт испепеляющего не уверен…
Думаю, в котлине уже есть автоматический вывод типов везде где это нужно, делать это везде где возможно только потому, что это возможно — не котлин вэй. Явные типы параметров и результатов нужны по многим причинам и никуда в котлине они не денутся.
Вы что-то конкретное хотели этим сказать?
А мне короткое имя в лямбдах в одно выражение вполне ок. В котлине вон есть it и тоже неплохо для простых выражений.
Не увидел в требованиях к новичку умение играть на дуде, это наверное опечатка.
понял, что контекст не нужен, т. е. еще проще:
inline fun <T, R> T.weakable(body: WeakReference<T>.() -> R): R = WeakReference(this).body()

inline fun <T, R> WeakReference<T>.ifSelfDefined(body: T.() -> R): R? = get()?.let(body)

class Test {

    fun someMethod() = weakable {
        api.getComments { list, exception ->
            ifSelfDefined {
                if (list != null)
                    updateUI(list)
                else
                    displayError(exception!!)
            }
        }

    }

}

и что важно, совершенно бесплатная абстракция выходит, как если бы мы сохраняли ссылку перед вызовом
С weak-ом такое вот решение еще можно, если уже котлин использовать:
class WeakContext<T>(self: T) {

    private val reference = WeakReference(self)

    val self: T?
        get() = reference.get()

    inline fun <R> ifSelfDefined(body: T.()->R): R? = self?.let(body)

}

inline fun <T, R> T.weakable(body: WeakContext<T>.()->R): R = WeakContext(this).body()

class Test {

    fun someMethod() = weakable {
        api.getComments { list, exception ->
            ifSelfDefined<Unit> {
                if (list != null)
                    updateUI(list)
                else
                    displayError(exception!!)
            }
        }

    }

}
Назвать статью «Как не наступать на грабли» стоило, если бы вы написали, как на них не наступать, а так это скорее «список граблей по инвентарному перечню», если вам прилетит в лоб, вы знайте, что действительно такие грабли есть. Статья хорошая, но очень в ней не хватает к каждому пункту, что же собственно нужно делать, чтобы на них не ступать, как создатели языка предполагали использовать все эти неочевидные моменты, видимо есть какие-то бестпрактис маневрирования между этими граблями, на мой взгляд эта информация очень лаконично дополняла бы список самих проблем и причин их появления.
Так ведь можно же, текущая лицензия так и работает, только получаешь то приложение за которые заплатил, без обновлений.
а я и раньше всё время enter нажимал и всё время удивлялся, что он не переходит на выбранную позицию
так это от плагина зависит. Какие-то добавляют функциональность, какие-то меняют существующую. С последними дела обстоят лучше, потому что они не требуют ничего для разработки. Пишешь себе код, а плагин углы режет. Конечно, есть и обратная сторона, но она не так значительна как вы говорите. Один раз добавить плагин в билдскрипт, когда он при первом старте свалился — не так уж и страшно, главное, чтобы это не превращалось в древнюю магию, когда невозможно понять, что происходит.
Почти любой проект требует для сборки какой-то свой билд-скрипт или какой-нибудь pom.xml и без него собираться не будет. Именно поэтому билд-файл обычно хранится вместе с проектом и не может быть причиной, почему нужно избегать применения плагинов, которые в этих билд-файлах настраиваются.
Генерировать код не так сложно, как можно подумать. Для этого есть очень неплохой инструмент, который работает как для java, так и для kotlin — называется apt (kapt для kotlin-а). Почему это нужно делать обязательно средствами языка?
Я не сказал, что способов обойти такие ситуации нет, я говорю лишь о том, что это может мешать разработке или тормозить её. Ведь если вы сделали рефакторинг до своих изменений, то их нужно отравить на ревью и вероятно от этой же ветки отпочковать и свой код, а возможно и еще какой-то код, который можно успеть сделать до прохождения ревью первого пр-а (по тому же принципу, что вы сами описали). А потом в ревью первого реквеста найдут нюанс, исправление которого повлечет за собой изменения во всех отпочкованных ветках, потому что по сути это всё были связанные изменения — а синхронизация и мердж этих веток это отдельные трудозатраты. Если же откладывать «на потом», то это с большой вероятностью может и вообще быть не сделано, да и нужно понимать, что отдельный реквест для рефакторинга тоже нужно посмотреть — это не бесплатно. И я описываю не какой-то придуманный кейз, а реальный случай из жизни. Еще раз хочу заметить, что я говорю лишь об «обратной стороне» этой практики. И о том, что в попытке сэкономить время и силы ревьювера, иногда бывает тратишь несравнимое количество своего времени и сил. Как и везде — нужно чувствовать грань.
Большой запланированный рефакторинг — да. А вот если ты добавляешь класс для реализации какой-то фичи и видишь, что хорошо было бы положить его вместе с некоторыми старыми классами в отдельный пакет, то тут ни о каком отдельном пр-е и говорить не приходится. И вот тут ты и думаешь: да, что-то много «лишних строк ревью — не буду в пакет выносить». И это только пример, таких ситуаций может быть много. Хотя, хочу заметить, что если рефакторинг можно продумать заранее, лучше конечно это сделать отдельным реквестом — я говорю лишь о том, что этот подход — палка о двух концах, где с другой стороны это бессознательное желание сократить количество измененных строк иногда даже в ущерб реальным потребностям разработки.
Правда есть и обратная сторона. Из за желания сделать пулреквесты небольшими, можно начать избегать рефакторингов по ходу разработки или просто «лишних» изменений, которые были бы уместны, улучшали структуру, читабельность, но не были сделаны, потому что это лишние строки кода. Я уж не говорю про перемещение файла в другой пакет или вынос внутреннего класса наружу — это вообще может стать катастрофой для пр-а «в десяток строк».
Сокращать размер пулреквестов — это хороший совет, но временами просто нереализуемый, если дело касается какой-то сложной фичи. Однако, стараться максимально разбить задачу на изменения, которые можно независимо выкатить, это действительно помогает и хорошему ревью и лучшему пониманию изменений и более простому отслеживанию проблем.

Information

Rating
Does not participate
Location
Москва и Московская обл., Россия
Registered
Activity