LINUX.ORG.RU

История изменений

Исправление zg, (текущая версия) :

Практический смысл есть. Вон в мире JavaScript тоже принято везде, где это возможно, писать const вместо let. Наверное, не просто так?

Если бы ты знал, то рассказал бы. Но ты не знаешь.

Ты же работаешь не один, верно? Или пишешь попенсорс и предполагаешь, что будешь работать не один? Всё, конечная. Теперь твой код это не только твоя проблема. Теперь всегда держи это у себя в голове. Иначе будут больно бить.

На текущем месте работы, где кто-то когда-то решил, что все аргументы должны быть final практически никому больше эти final в аргументах не нужны и при первой же возможности (например в тестах) их не пишут. То есть это просто чьё-то самодурство и не более того. Я работал во многих компаниях и то тут то там появлялись примеры такого самодурства. Например в другой компании зачем-то написали целый фреймворк для юнит тестирования (поверх junit), который проверял абсолютно все методы, включая private, на рандомно кривые параметры. Это приводило к тому, что люди боялись или ленились нормально разделять свой код на части и писали сотни строк подряд только из-за этого. Потому что иначе private метод в 3 - 5 строк превращался в метод на 15 - 20 строк только из-за глупых проверок, спущенных нам сверху.

Недавно разгребал чей-то говнокод. Разработчик почему-то подумал, что дать одной и той же переменной разный смысл в разных контекстах - отличная идея. В начале user значит одно, в середине что-то другое, в конце третье. Получается лапша. Ты сидишь и пальцем водишь по монитору, отслеживая, где и почему меняется семантика переменной. Тратишь время и силы, вместо того, чтобы делать работу. Какая-то нифига не самодокументируемая шляпа. :(

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

В конце забиваешь на всё и переписываешь. Создаёшь одну, вторую и третью переменную с говорящими именами (при хорошем нейминге у тебя не будет нужны в user и user2), создаёшь их в разных участках кода по мере необходимости, указываешь const или final спецификаторы, чтобы эту семантику впредь никто не менял. Теперь ты сразу же глазами видишь, из каких основных, независимых друг от друга, блоков состоит функция. Сразу всё становится понятно, и волосы возвращают прежний блеск.

Без final в аргументе user переменная user2 не нужна. Ты просто присваиваешь user текущего пользователя, если тебе в user передали null. Что может быть проще и понятнее? Иначе придётся копировать user в user2 (можешь дать ему более читабельное название, это не важно), а если пришёл null, то делать какой-то фолбек, как было сказано выше. Далее тебе нужно будет не перепутать эти две переменные в дальнейшем коде. Короче, это глупость и всё из-за final в аргументе user.

Конечно, каргокультровать тоже не надо. Где в этом есть настоящий смысл - убирай final и мутируй ссылку. Желательно не меняя её семантики и не размывая её изменения по всему телу функции.

Ну то есть ты тоже за то, чтобы программист сам решал, без эффективных менеджеров и прочих корпоративных бюрократов, нужен ли ему final тут или там или нет?

А плюсовая и растовая иммутабельность это вообще немного другая тема. Прикинь, что у тебя есть гарантии, что тот или иной метод не модифицируют внутреннее состояние объекта. Это вообще круто! Сразу в голове появляется понимание, что на текущей строке может произойти, а чего произойти не может ни при каких обстоятельствах. Это снова выражение намерений программиста + гарантии. Этими гарантиями уже пользуются другие программисты и, конечно, компилятор.

Ну вот стоило добавить const перед std::string& и у него тут же пропал append(), что и сделало такой стринг неизменным. По-моему это очень хорошая и полезная вещь и очень жаль, что в Java ничего похожего нет. Ошибка компиляции - это гораздо более сильная вещь, чем удержание в голове подробностей той или иной реализации.

Исходная версия zg, :

Практический смысл есть. Вон в мире JavaScript тоже принято везде, где это возможно, писать const вместо let. Наверное, не просто так?

Если бы ты знал, то рассказал бы. Но ты не знаешь.

Ты же работаешь не один, верно? Или пишешь попенсорс и предполагаешь, что будешь работать не один? Всё, конечная. Теперь твой код это не только твоя проблема. Теперь всегда держи это у себя в голове. Иначе будут больно бить.

На текущем месте работы, где кто-то когда-то решил, что все аргументы должны быть final практически никому больше эти final в аргументах не нужны и при первой же возможности (например в тестах) их не пишут. То есть это просто чьё-то самодурство и не более того. Я работал во многих компаниях и то тут то там появлялись примеры такого самодурства. Например в другой компании зачем-то написали целый фреймвор для юнит тестирования (поверх junit), который проверял абсолютно все методы, включая private, на рандомно кривые параметры. Это приводило к тому, что люди боялись или ленились нормально разделять свой код на части и писали сотни строк подряд только из-за этого. Потому что иначе private метод в 3 - 5 строк превращался в метод на 15 - 20 строк только из-за глупых проверок, спущенных нам сверху.

Недавно разгребал чей-то говнокод. Разработчик почему-то подумал, что дать одной и той же переменной разный смысл в разных контекстах - отличная идея. В начале user значит одно, в середине что-то другое, в конце третье. Получается лапша. Ты сидишь и пальцем водишь по монитору, отслеживая, где и почему меняется семантика переменной. Тратишь время и силы, вместо того, чтобы делать работу. Какая-то нифига не самодокументируемая шляпа. :(

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

В конце забиваешь на всё и переписываешь. Создаёшь одну, вторую и третью переменную с говорящими именами (при хорошем нейминге у тебя не будет нужны в user и user2), создаёшь их в разных участках кода по мере необходимости, указываешь const или final спецификаторы, чтобы эту семантику впредь никто не менял. Теперь ты сразу же глазами видишь, из каких основных, независимых друг от друга, блоков состоит функция. Сразу всё становится понятно, и волосы возвращают прежний блеск.

Без final в аргументе user переменная user2 не нужна. Ты просто присваиваешь user текущего пользователя, если тебе в user передали null. Что может быть проще и понятнее? Иначе придётся копировать user в user2 (можешь дать ему более читабельное название, это не важно), а если пришёл null, то делать какой-то фолбек, как было сказано выше. Далее тебе нужно будет не перепутать эти две переменные в дальнейшем коде. Короче, это глупость и всё из-за final в аргументе user.

Конечно, каргокультровать тоже не надо. Где в этом есть настоящий смысл - убирай final и мутируй ссылку. Желательно не меняя её семантики и не размывая её изменения по всему телу функции.

Ну то есть ты тоже за то, чтобы программист сам решал, без эффективных менеджеров и прочих корпоративных бюрократов, нужен ли ему final тут или там или нет?

А плюсовая и растовая иммутабельность это вообще немного другая тема. Прикинь, что у тебя есть гарантии, что тот или иной метод не модифицируют внутреннее состояние объекта. Это вообще круто! Сразу в голове появляется понимание, что на текущей строке может произойти, а чего произойти не может ни при каких обстоятельствах. Это снова выражение намерений программиста + гарантии. Этими гарантиями уже пользуются другие программисты и, конечно, компилятор.

Ну вот стоило добавить const перед std::string& и у него тут же пропал append(), что и сделало такой стринг неизменным. По-моему это очень хорошая и полезная вещь и очень жаль, что в Java ничего похожего нет. Ошибка компиляции - это гораздо более сильная вещь, чем удержание в голове подробностей той или иной реализации.