Комментарии 30
Если послушать доклады Бреслава, он обычно говорит, что они стремились по максимуму все делать явно всегда, если только это не должно происходить в любом случае (например, автокасты).
В защиту можно сказать, что это далеко не новая проблема и в Котлине она стоит далеко не так остро, как в груви.
Ну и мои пять копеек: даже с именованными переменными стоит избегать многократно вложенных функций, оно плохо читается от природы.
По поводу вложенности — полностью с Вами согласен.
Самая дичь, с которой приходится жить — это возможность переопределить get()
у val
и возвращать значения динамически, что нехило ломает концепцию неизменяемых значений и иммьютабилити в принципе :(
val a: Int
get() = Random().nextInt()
Особенно печально, когда val
определен в интерфейсе и ты не знаешь, пока не заглянешь в реализацию, immutable этот val или нет.
val не должен меняться => 2 доступа к одному val должны возвращать одно и то же значение.
Ээ, я ничего не ломаю, язык позволяет так делать, а нам приходится с этим мириться.
Я не мог правильно прочитать сообщение, на которое ответил — я просто представить себе не мог, что в каком-то языке так можно делать.
Это же ужас!
Спасибо за пояснение.
Нет, я знал, что в котлине не уважают иммутабельность (те же их билдеры не могу существовать без мутабельности, что меня удивило при разборе HTML Builder), но что всё настолько запущено я не предполагал.
И?
В Kotlin val
часто работает как final
поле в Java, вот final
в таком случае оказывается более строгим, чем val
, это и печалит.
И? Я это понимаю :)
Бесит то, что Котлин весь такой модный и форсит иммутабельность (что классно), но понять, что объект реально immutable невозможно без чтения исходников/байткода. В Java это очень просто — public final
поле это гарантирует (unless reflection). Подсказка со стороны IDE была бы очень не лишней (пойду тикет заведу).
Ну и зачем было делать этот it
? Добавили проблему, теперь пытаются решить.
// Намного лучше читается так, почти как английский текст
(1..100).filter{ it > 50 }.map{ it * 2 }
// Хуже читается, появляются доп. символы
(1..100).filter{ x -> x > 50 }.map{ x -> x * 2 }
По поводу «проблем» которые не будут чиниться — то что затронуто в этой статье не больше и не меньше чем code-style. То бишь что тут чинить если это by-design заранее обдуманные случаи использования.
`it` в принципе не предназначен для callback-ов, в документации так и написанно — именуйте параметр кроме простейших случаев. Функция `let` действительно редко встречается в моей практике, но она незаменима для цепочек вызовов с функциями принимающими аргумент, например `mylist.let {LinkedList(it)}.filter {it > 0}`. В случае с `with` мне кажется очевидным что `getLatestComment()` не относится к `dbHelper`, но если это не так, то действительно лучше обойтись явными вызовами по старинке.
В общем, я согласен с автором что иногда неприятности встречаются в коде, но не согласен что это вина языка. Надеюсь давно обещанный продвинутый форматер решит подобные проблемы.
fun f() {
with ("string") str@ {
with (123) num@ {
println(this@str.hashCode() + this@num.hashCode())
}
}
}
fun f() {
val str = "string"
val num = 123
println(str.hashCode() + num.hashCode())
}
Также использование данного именования явно указывает на проблему в коде (тот самый момент, когда говорят, что код «пахнет»).
Спасибо за то, что напомнили, что можно ещё и так использовать with =)
Те темы, которые вы поднимаете, крайне важны для проектов, где больше одного разработчика, или, более того, много разработчиков разного уровня.
С удовольствием прочитаю следующую часть
val user = response?.user ?: return
val name = user.name
как по мне но такие «ретурны» в коде могут быть очень малозаметными и в итоге код будет выполнятся иначе чем ожидает программист — да и найти такой «выход» в полотне кода (даже на 10 строк) будет сложно
Kotlin: без Best Practices и жизнь не та. Часть 1