Pull to refresh

Comments 174

Имей идею.

Читай «используйте предварительное проектирование». Дизайн компонентов, который нельзя представить в голове в течении 10 минут стоит вначале воспроизвести в виде UML.
Также я всегда использую var никогда не использую явное типизирование (ну только когда выхода нет). Я так же стремлюсь всегда давать очень короткие имена переменным i,d,v,k для меня не проблема

Лично для меня оба весьма спорных утверждения, но может Вам так действительно удобнее.
Если вы дебажите свой код, который только что написали, что-то пошло не так.

Хм, Вы всегда пишете код, который правильно работает при первом запуске?
UFO just landed and posted this here
Естественно, «что-то не так». Только вот от банальной опечатки которую порой и сходу отловить нельзя никто не застрахован. И найти ее до запуска тестов/либо просто запуска приложения невозможно. Собственно есть простая статистика сколько программисты проводят времени за отладкой, и даже в самых качественных продуктах с профессионалами разработчиками процент этого времени весьма высок. Так что утверждение автора как минимум спорно.
Я не это имел ввиду, я имел ввиду, если вам не понятно, что пошло не так и приходится дебажить для этого, то что-то не то у вас. Это все про только что написанный код.
Так вы МакКоннела-то прочитайте. У него, если что, рекомендуется любой, даже работающий код проходить дебаггером хотя бы единожды.

(Потому что ни один код не существует сам по себе, и его поведение всегда будет зависеть от окружения, которое программисту очень часто неподконтрольно)
Если не секрет, какой у автора стаж разработки за деньги? Хотелось бы всё же увидеть примеры кода. В статье много спорных утверждений. К тому же, уровень владения русским языком и стилистика текста наводят на мысли.

>Если вы дебажите свой код, который только что написали, что-то пошло не так
Это почему? Я реализовал обработку сложной бизнес-логики, три метода по пол-экрана, и хочу увидеть вживую, всё ли происходит, как задумано — что у меня пошло не так?
три метода по пол-экрана? вы точно что-то делаете не так.
все зависит от количества строк, которые помещаются на экране. И, зачастую, функция в пол экрана это не большая функция, тем более в эпоху широкоформатников
исторически сложилось, что «экран» — это 80х25… :)
У нас видимо разная история
мой широкоэкран дома — 1366х768, и даже на нём помещается в Kate 45 строк. и лично я бы прибил за метод в 20-25 строк длинной. а над человеком, который критикует статью о рефакторинге и пишет такие методы очень сильно бы посмеялся.
Признайтесь сразу, вы читали книгу, название которой вынесено в название блога, куда вы пишете?
действительно, странно выглядит эта статья в данном блоге. после невероятно полного и развернутого обзора всех её тезисов в данной книге
Я ее в песочнице оставил, я не знаю кто ее перенес в этот блог. Книгу я читал, но статья не о том, как получить «совершенный код», скорее о том, как получить работающий код, который неплох, в зжатые сроки.
А для разработки в сжатые сроки все вообще делается не так.

Потому что работающий код для сжатых сроков — это код, который просто работает. Для него не нужна идея, для него нужно понимание задачи и навыки разработки.
UFO just landed and posted this here
Это не «идея» (и тем более не идея в понимании автора). Это бизнес-задача.
Для проектов в сжатые сроки нужно обрезать функциональность, забывая про финтифлюшки, а не писать убогий код — потом будет поддержка, так вот на поддержке и можно добавить недостающее, а не испытывать боль в некотором месте по поводу, что через это место писался код.
Впрочем, заниматься искусством тоже не стоит, если не планируется расширение
«Для проектов в сжатые сроки нужно обрезать функциональность, забывая про финтифлюшки,»
Это не решение уровня кода, это решение уровня бизнес-анализа/управления проектом. То есть — за пределами обсуждения.
а иначе, получается — пиши говнокод!
Во-первых, не надо писать говнокод. Большую часть задач можно решить быстро, брутально, но все еще без говнокода. Не надо недооценивать копипаст и брутфорс.

Во-вторых, если у вас нет выхода, а выдать решение нужно в течение 15 минут, то лучше написать говнокод, чем не выдать вообще ничего. Потому что говнокод потом можно уничтожить, а вот сорванную презентацию вернуть сложно.
> если у вас нет выхода
Выход всегда есть — даже если вас съели! А чтобы не съели, нужно быть убедительным на стадиях до написания кода )))
Я бы даже сказал, что 2 выхода)
У меня 8 лет стаж разработки за деньги. Я смотрю пока вопрос про дебаг стал, пока, самым главным. Если вы только что писали код, то вы его практически на память должны знать. И соответственно когда что-то не правильно работает, сразу понятно где и что. Если для того чтоб найти ошибку приходится дебажить, с кодом явно что-то не так. И конечно же я не всегда пишу код который сразу работает, но так происходит в большенстве случаев. Часто дебажить свой код приходится когда используются сторонние разработки, особенно когда опыта работы с ними не много.
По поводу языка. Данная сатья не претендует на звание научного труда. Она имеет философский характер и это мои мысли, поэтому и написана в свободном стиле. Именно из-за этого и примеры не приводятся.
>Если вы только что писали код, то вы его практически на память должны знать.

Я написал модуль для построения верхней и нижней обрамляющих поверхностей для облака точек в полтысячи строк кода, который интенсивно вызывает уже готовые модули. Могу ли я держать в голове весь код с его ветвлениями?
Если размер модуля полторы тысячи строк — что-то уже не так.
«Часто дебажить свой код приходится когда используются сторонние разработки, особенно когда опыта работы с ними не много.»
Фишка, понимаете ли, в том, что в крупном проекте почти всегда используются «сторонние разработки» (даже когда «сторона» — это программист из-за соседнего стола). И поэтому ты никогда на 100% не уверен, что именно не работает.
> Если вы только что писали код, то вы его практически на память должны знать. И соответственно когда что-то не правильно работает, сразу понятно где и что. Если для того чтоб найти ошибку приходится дебажить, с кодом явно что-то не так.

Это так если кода — строк 10-20, он весь находится в одном файле и не взаимодействует с другими подсистемами проекта. Да, вы помните что написали и знаете свой код. Но ваш код не работает в вакууме, даже если он идеален.
Утрирую конечно, но при больших объемах кода и размерах проекта редко когда он сразу начинает работать так как планировалось, и то потом приходится долго тестить, писать автоматизированные тесты и дебажить дабы исключить даже возможность возникновения side-эффектов при различных входных данных.
По поводу языка: я бы рекомендовал вам поставить спелл-чекер под ваш любимый браузер. Вопросов по владению языком у читателей станет гораздо меньше.
Забыл добавить «как это делаю я».
По поводу имен переменных. У меня есть знакомый, который ВСЕГДА пишет примерно так:
function func(a, b, c) {}

при этом говоря «а зачем называть входящие переменные, посмотрят внутри функи, что они делают и поймут что туда пихать нужно». Названия ВСЕГДА должны быть говорящими или следовать соглашению (многие сокращают на уровне соглашения по написанию библиотечные для проекта классы, типа
hr = new HttpResponse()

В остальных случаях они должны быть говорящими и «сам догадается» это ответ ленивого человека.
весьма спорно про названия переменных, особенно когда вы не один на этот код будете смотреть потом
Я бы сказал не спорно, а в корне неверно.
Исключение: короткие имена переменных очень удобны для счетчиков циклов (да и то если цикл короткий и не предполагает разрастания на 1-2 экрана). Сам привык к этому еще со времен PL/I (если кто помнит — i,j,k,etc.): коротко плюс сразу видно, где нормальная переменная (долгоживущая), а где временная финтифлюшка, нужная только для данного цикла.
Это просто капец какая смешная статья. Перенесите в Хабраюмор. Статья примерно поровну делится на переписанные у Макконнелла и Фаулера утверждения капитана Очевидность и собственные идеи, которые все до одной не верны.

>имена переменным i,d,v,k для меня не проблема, ибо функции маленькие все понятно из контекста. Зачем писать currentNode если можно написать просто n и при это все равно все ясно?

Кому ясно? Вам ясно? А когда таких функций будет 1000 — тоже будет ясно? А через 5 лет? Или Вы не планируете, что Ваша программа столько проработает? А Junior-программеру будет ясно? Или ну их в пень?

>Если вы дебажите свой код, который только что написали, что-то пошло не так.
Правда? Советую Вам посмотреть офигенную презентацию автора Sphinx, которая называется «Как перестать программировать». Так вот он там советует для критически важного кода обязательно пройтись хотя бы раз в дебаггере, проследить значения переменных и пути алгоритмов. Если код будет вызываться редко, но он очень важен — пройтись в дебаге вовсе не будет лишним.

>Стоит реже компилировать свой код, вообще стоит больше писать меньше собирать.
Ага, знаем мы таких разработчиков — налабают мегабайт кода не компилируя, коммитнут, а потом от тестеров приходят замечания «нужно немного поправить», после которых оказывается, что просто нужно все переписать, поскольку автор кода изначально исходил из неверных принципов или не понял используемое API.

>Однако не советую сильно настраивать под себя среду.
Ага, не ставьте Resharper\VassistX\CodeRush, которые ускорят Вас в 2 раза, потому что раз в год нужно будет помочь коллеге, а у него такого плагина может не быть.

> Кому ясно? Вам ясно? А когда таких функций будет 1000 — тоже будет ясно?
имхо, если вам в методе надо уточнять имена счётчиков и прочих простых вещей, то это значит две вещи: а) вам нужно отDRYить код б) вам нужно расщепить метод. Моё субъективное мнение — идеальная длинна метода — 4-5 строк. в такой длинне не запутаешься даже с 1000 функций. а если запутаешься, то значит весь API спроектирован неверно. и именами переменных здесь уже ничего не спасёшь. Кстати, 1000 функций в одном модуле — тоже пример проблем в коде куда более высокого уровня, чем имена переменных.

> Советую Вам посмотреть офигенную презентацию автора Sphinx
Вы ещё посоветуйте посмотреть презентации разработчиков ПО для шаттлов.

Ничего не хочу сказать о качестве кода Sphinx, но в разных технологиях, разных сообществах и в разных языках также и разные стандарты качества и рефакторинга. Автор это забыл упомянуть, но и вы похоже тоже.
>идеальная длинна метода — 4-5 строк
У Вас получается программировать в таком стиле? Пример в студию. Я склоняюсь к 15-25 строкам (и то не всегда получается).
я Ruby-кодер. поверьте на слово, на этом языке 4-5 строк — это порой даже много.
А после вас потом кто-то может понять, или пока такой проблемы не стояло? :)
а по делу ответить нечего?
Что может быть больше «по делу», чем поддержка существующего кода, написанного с теми или иными соглашениями, о которой речь и идёт в треде?

Я сам перловик, и у нас даже одной строки может быть черезчур. Поэтому, в частности, я для себя выработал правило комментировать в терминах предметной области каждую группу логически-связанных предложений (т.е. если свербит отделить предложения пустой строкой — имеет смысл прокомментировать выделенный кусок). И таких кусков по 3-10 строк в методе может быть до десятка — неужели каждый заменять отдельным методом и его вызовом? Пока никто не жаловался, что у меня непонятный код, а вот у челов, которые меньше года работают и сваливают, я такого read-only кода навидался.
больше по делу может быть парирование аргументами, а не беспочвенный намёк на некомпетентность оппонента.

по части ваших логических кусков кода — когда начнёте пользоваться Unit-тестами, поймёте, о чём я говорил.
Если вы за намёк приняли мой вопрос про читаемость вашего кода — то я это совершенно серьёзно спросил (а смайл относился к «не стояло»), т.к. я неоднократно видел руби-код и его читаемость для человека, привыкшего к C-подобному синаксису — спорна. Соотвественно, я представил себе количество информации, вмещающееся в 5 строчек и у меня возникло 2 опции: либо это write-only код, либо то, что делает этот метод относится к тривиальной минимальной объединённой логически единице кода. Оба рассматриваемых варианта породили лишь вопросы.

По поводу юнит-тестов вы имели в виду утилиты, которые проверяют покрытость модулей/методов тестами? Т.к. ничто не мешает тестировать толстые методы, если определён интерфейс взаимодействия.
когда толстые методы разделены на методы по 4-5 строк их намного проще тестировать. часто таких тестов даже хватает, чтобы, как написал автор, ничего не дебажить. ну и проблема тестирования больших методов ещё и в том, что по большей части это получается лишь чёрный ящик. прозрачный ящик с проходом по всем циклам и условиям на больших методах сделать трудно, и 100% покрытие не выйдет.
Но зато и тестов для коротких методов надо гораздо больше написать.

Кроме того, не забывайте, что даже если все короткие методы будут согласно тестам идеально работать, ошибки в вызывающем их модуле все равно возможны: не так состыковали, не все комбинации параметров предусмотрели и т.д. и т.п. Эти возможные ошибки тоже ведь надо покрыть тестом кода верхнего уровня, не так ли? В итоге получается, что выиграша по тестам может быть и не быть, а в отдельных случаях будет даже проигрыш.
дык поверх юнит тестов как бы функциональные и интеграционные делать — это нормальная практика. а более подробное тестирование в принципе не может быть хуже.
Вы сейчас о чем? Я вообще-то говорил о проигрыше в дополнительных накладных расходах при дроблении методов под правило «4-5 строк в методе», а не о проигрыше в качестве тестирования.
И тут уже надо смотреть в каждом конкретном случае — в итоге мы больше выигрываем или теряем? Не факт, что всегда мы будем в выигрыше.

И вообще, оптимальное кол-во строк в функции/процедуре/методе определяется балансом очень многих факторов, не только тестирования (например, язык программирования, задача, длительность сопровождения, изменяемость кода, повторная используемость, трудоемкость и качество тестирования и т.д. и т.п.) и поэтому даже внутри одного проекта может сильно отличаться. Поэтому правила типа «N строк на метод и баста!» отношу к оторванным от жизни догмам из серии «Мне это помогло — значит и тебе поможет».
Я что-то там совсем не вижу критику ваших «4-5 строк в методе».
я не про это

> разных технологиях, разных сообществах и в разных языках также и разные стандарты качества и рефакторинга. Автор это забыл упомянуть, но и вы похоже тоже
и ещё:
> Моё субъективное мнение — идеальная длинна метода — 4-5 строк.

> я Ruby-кодер

я до сих пор не могу понять. вы со своим перлом говорите мне, что мне в Ruby не надо писать методы по 4-5 строк?

я честно говоря устал вести этот спор и не вижу в нём продуктивности.
Ни в обсуждаемой статье, ни в комментарии tangro, и в вашем возражении ему (см. вашу ссылку выше) — нигде не было привязки к конкретному языку программирования. Следовательно, контекст обсуждения — языки программирования в целом. И в этом контексте ваше правило «4-5 строк в методе» является в корне неверным. Отсюда и последовавшая критика в ваш адрес.

я честно говоря устал вести этот спор и не вижу в нём продуктивности.
Это ваша вина.
Видите ли, здесь очень мало телепатов, которые могут догадаться, что когда вы в качестве контраргумента привели очень частный случай (ваш опыт в рамках конкретного языка), то дальнейшее обсуждение должно ограничиться рамками именно вашего частного случая, а не оставаться в рамках изначальной статьи.
> И в этом контексте ваше правило «4-5 строк в методе» является в корне неверным

это исключительно ваше мнение. и я за вас очень рад. и про частный случай тоже. и не надо мне тут никакую вину приписывать, это тоже ваше мнение.

моё мнение — что 15-25 строк в одном методе на любом языке — это быдлокод.
По существу своей вины в искусственном сужении контекста вы ответить так ничего и не смогли.

это исключительно ваше мнение.
Какое же это «исключительно мое», раз я уже 3-ий по счету, кто с вами по этому поводу спорит? ;)

моё мнение — что 15-25 строк в одном методе на любом языке — это быдлокод.
А вот это действительно исключительно ваше мнение. ;)
вы знаете, с вами очень интересно спорить. наверное было бы. если бы вы считали целью спора найти истину, и хоть как-то пытались обдумать аргументы оппонента, а не ссылаясь на других, не более авторитетных, чем вы, источников, пытались истерично доказать свою «единственно верную» точку зрения.

но я опять забыл, на каком я сайте.
Всегда считал, что поиск истины возможен только с помощью аргументов/контраргументов, от приведения которых вы упорно уклоняетесь. Но у вас, конечно же, может быть своё, индивидуальное мнение на этот счет. ;)

1. Какие ваши контраргументы по поводу отсутствия у вас сужения контекста должен я обдумать, если вы вообще не привели? :)
Процитируйте их, если я неправ.

2. С каких пор утверждение «исключительно мое» должно опровергаться не кол-вом, а авторитетностью источников? Вы что-то новое в русском языке сейчас изобретаете. :)))

3. В своем глазу бревна не видите. Ваше утверждение про быдлокод в 15-25 строк вообще без каких-либо аргументов. И откуда эти 15-25 строк взяты (с потолка что-ли?) — тоже не аргументировано.
Ну давайте ещё по APL-программистам равняться будем: у кого функция расчёта выпуклой оболочки вылезла за 140 символов — тот что-то делает неправильно.

И на рудники, на урановые рудники.
Пять балов! У меня serve_request в пол экрана не влез :)
в следующий раз хоть на дату смотрите, ок?
это студенческая работа с третьего курса, ей три года в обед
имхо, если вам в методе надо уточнять имена счётчиков и прочих простых вещей, то это значит две вещи: а) вам нужно отDRYить код б) вам нужно расщепить метод.

Тем не менее я считаю, что лучше по возможности давать переменным говорящие имена. Это просто проще читается (простите за тавтологию), а не к этому ли (в частности) мы стремимся в совершенном коде?
А можете дать ссылку на презентацию? С ходу найти не получилось
На самом деле не представляю себе рабочего окружения, где у одного шарп программиста есть решарпер, а у второго — нету.
Я в таком работаю.
А почему нет? У нас треть где-то не ставит себе решарпер.
Ага, знаем мы таких разработчиков — налабают мегабайт кода не компилируя, коммитнут, а потом от тестеров приходят замечания «нужно немного поправить», после которых оказывается, что просто нужно все переписать, поскольку автор кода изначально исходил из неверных принципов или не понял используемое API.

Совет то верный, на самом деле. Это совет от МакКонела, чтобы научится лучше понимать код. Т.е. реже полагаться на ошибки компилятора и больше полагаться на собственные способности. Т.е. лучше следить за своим кодом
У МакКоннела причина описана другая: после сломавшейся компиляции у человека включается стимул как можно быстрее поправить эту конкретную ошибку, не разбираясь в причинах (второе английское издание, 231 страница). Он предлагает компилировать тогда, когда вы внутренне уверены, что все работает. Это не «часто» и не «редко», это «когда работает».
Современные IDE либо инкрементально компилируют код, либо его хотя бы парсят — обычно этого достаточно. Остальные ошибки выловить можно только тестами или дебагом
Ну если у вас есть 1000 функций, которые используют одну переменную, то как ее не назови, дебажить вам весь этот код прийдется точно, причем скорее всего не раз.
Если что-то понятно из контекста сечас, оно будет понятно и через 5 лет.
Про джуниоров отдельный разговор, им всеравно врядли будет понятно, как не напиши, а когда они разберуться в конечном итоге то им опять же всеравно как называется переменная.
По этому поводу снизу есть примеры с foreach это именно то, что я имел ввиду.

Про поводу коммитить не компилируя, можно меня вот лицом ткнуть туда где я про это писал? К томуже я не очень осилить могу как частая компиляция помогает лучше понять используемое АПИ? Разве что с какимито проблемами столкнуться можно немного раньше.

> Resharper\VassistX\CodeRush
Все эти замечательные вещи не совсем бесплатные, и не в любой компании могут стоять. Смена работы, изменение какойто политики и тп, могут приводить к проблема, дефолт есть дефолт.
Мне например по долгу службы приходится часто сидеть за чужими компьютерами и меня например раздражает даже тот факт, что клавиатура другая, не говоря уже про настройки среды.

Вообще совершенно ниачемный коммент, набор «умных» выссказываний отсылка на какуюто презентацию, поставлено много «глубоких вопросов», но народ хорошо поплюсовал, надо будет это запомнить.
«Если что-то понятно из контекста сечас, оно будет понятно и через 5 лет. „
Отнюдь. Контекст постоянно меняется. Сегодня вы еще держите в голове общую картину, а через пять лет этого не будет.
Мне кажется с таким подходом к коду на 5 лет автор не задержится в одной компании :)

> Вообще совершенно ниачемный коммент, набор «умных» выссказываний отсылка на какуюто презентацию, поставлено много «глубоких вопросов», но народ хорошо поплюсовал, надо будет это запомнить.

Честно говоря в этом абзаце вы практически описали вашу статью.
UFO just landed and posted this here
«Причем кода, иногда, требуется написать действительно много, и его не получится разбить на множество мелких изменений»
Последний раз, когда я имел дело с изменением, описанным таким образом (по сути, я это изменение разбирал за разработчиком, ушедшим в отпуск), оно все равно поделилось на множество мелких изменений.
UFO just landed and posted this here
Во-первых, он не единичный, просто я привел самый характерный для меня — когда кто-то счел, что это один неделимый коммит, а оказалось не так. А во-вторых, я и за собой регулярно замечаю, что изменение, которое я раньше счел бы неделимым, сейчас я могу реорганизовать.
> Кому ясно? Вам ясно? А когда таких функций будет 1000 — тоже будет ясно? А через 5 лет? Или Вы не планируете, что Ваша программа столько проработает? А Junior-программеру будет ясно? Или ну их в пень?

Всему надо знать меру. Для счётчиков сойдут однобуквенные имена, ведь контекст операторов понятен всегда. А если уж и такое непонятно, то, может, кодер не ахти?
UFO just landed and posted this here
Да сколько можно уже «трыньдеть» на эту тему, работать надо…
Procrastinators, unite! Tomorrow.
Или работать хорошо, или совсем не работать! )))
UFO just landed and posted this here
Я, собственно, всегда считал, что человек, который не способен грамотно и связно излагать свои мысли на родном языке, скорее всего плохой программист.
В случае с хаброй нужно еще делать скидку на то, что русский для автора может быть и не родным и не основным языком.
Автор об этом нигде ничего не сказал. Поэтому не вижу причин делать скидки.
Да я тоже не в курсе откуда автор, но неоднократно обнаруживал в профиле автора топика/комментария с ошибками израиль, чехию, англию и прочее. Поэтому не спешу с выводами.
… и в профиль я тоже посмотрел.
Я живу на Украине, русский для меня родной язык, в школе у меня всегда была 3ка по русскому языку, я плохой программист?
Ребята вы бы еще сказали, что если человек не может подтянуться 10 раз на перекладине, у него нет силы воли, поэтому он скорее всего плохой программист.
«в школе у меня всегда была 3ка по русскому языку, я плохой программист?»
Нет. Прочитайте внимательно то, что написано: «человек, который не способен грамотно и связно излагать свои мысли на родном языке, скорее всего плохой программист».

То, что человек не умеет писать грамотно (кроме дисграфии), скорее всего показывает на недостаточность внимания и/или аккуратности. В коде у него будет то же самое. Да, компилятор отловит, но без компилятора он будет ошибаться чаще. А в любом месте, где нет строгой валидации, неспособность написать слово (идентификатор) правильно приведет к неотлавливаемым ошибкам. И примеров этому я видел больше одного.

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

Но с тройкой по русскому языку в школе это все никак не связано.
Вот-вот. Сразу глаз кольнули «пишите» вместо «пишете», «потянуться» вместо «потянутся»… Эти же слова даже с разным ударением произносятся.
Автор — фанат водопадной модели?

UFO just landed and posted this here
Как правило сделать код работающим очень не сложно


Только не в том случае, когда происходит race condition.
Parallel Programming это вообще отдельная сложная тема. Если кратко — то синхронизация наше всё, и при отладке кода надо читать его во второй (n-ный) раз пошагово, смотря, какие у нас общедоступные ресурсы, учитывая, что они могут поменяться в любой момент, если код не находится в критической секции
Даже если находится в критической секции ) Ибо всегда может найтись тот, кто чихать хотел на наши усилия по синхронизации (как правило, по незнанию).
В целом статья ни о чем.
Много воды на одно смысловое заключение.
Пардон, а Вы не заметили, что концентрат информации дают только справочники (reference), а вот все статьи, книги обычно сводятся к одной мысли? «афоризм — это хорошо отредактированный роман» (ц)
>>> имена переменным i,d,v,k для меня не проблема, ибо функции маленькие все понятно из контекста. Зачем писать currentNode если можно написать просто n и при это все равно все ясно?

Знаете, я вот только пол-часа назад закончил разбираться в одном классе переданного мне проекта. Большая часть переменных-членов в нем были названы в стиле k, kk, f1, fw, lp. Я почти час сидел, разбирался что же они значат и рефакторил, рефакторил, ругался, снова рефакторил… Потом вздохнув с облегчением я решил зайти на хабр, ткнул в первую попавшуюся статью… и тут читаю эту ужасную фразу. Одним словом, мне очень сложно сейчас описать эмоции, которые я испытываю :)
Просто не надо бросаться в крайности. Там же ясно написано: если все понятно из контекста, то трудолюбивому:

foreach(SomeStecialDictionary someStecialDictionaryItem in someSpecialDictionaryCollection)
{
someStecialDictionaryItem.DoIt();
}

стит предпочесть:

foreach(var i in someSpecialDictionaryCollection)
i.DoIt();

Ваш К.О. :)
Полностью поддерживаю! Давайте не бросаться в крайности. :) вместо

foreach(SomeStecialDictionary someStecialDictionaryItem in someSpecialDictionaryCollection)
{
someStecialDictionaryItem.DoIt();
}

стоит предпочесть

foreach(var dictItem in someSpecialDictionaryCollection)
{
dictItem.DoIt();
}

someSpecialDictionaryCollection.ForEach(i => i.DoIt());
someSpecialDictionaries.ForEach(d => d.Dolt());
А при чем тут Lisp? Цитата из c#.

У того же MакКоннела написано: don't program on a language, program into a language.

То, что я описал — логичный функционал, который повышает читаемость кода. Все.
А что, есть какие-то проблемы реализовать такое поведение для любого IEnumerable?
UFO just landed and posted this here
Он про то, что метод ForEach доступен только для типа List.
UFO just landed and posted this here
Проблем нету, я только хотел уточнить ваше недопонимание :).
Отдельное спасибо за «Сохраняй фокус». Это для меня действительно проблема.

Хочу добавить парочку замечаний. Вместо alt+shift+f10 можно использовать не менее дефолтный ctrl+[точка]. Использование переменных, состоящих из одной буквы, лучше ограничить теми случаями, когда созданные переменные будут использоваться только в той же строчке (лямбды) либо сразу (и только) в следующем выражении. Иначе при чтении подобного кода придется постоянно бегать глазами до объявления и обратно, чтобы понять, что здесь происходит и зачем.

Насчет простоты я бы еще добавил, что не нужно делать систему более умной, гибкой и расширяемой, чем это требуется. Прикручивать фреймворки и паттерны — это все очень весело, но нужно следить за тем, чтобы вся эта развесистая инфраструктура не превратилась в гору мусора, за которой уже нельзя будет разглядеть бизнес-логику.
Спасибо, я не знал, про ctrl+[точка]!
> До того как сесть что-то писать, вы должны более менее представлять как это все будет работать

Автор — фанат водопадной модели?

> Шаблоны проектирования, иерархии классов, элементы функционального программирования это все замечательные вещи. Однако стоит по возможности стараться все делать как можно проще.

Один умный человек где-то рассказывал что большая часть шаблонов элементарно реализуется на ФП. Вообще, коллективная практика показывает, что хочешь сделать проще — пиши в функциональном стиле, если нет хороших причин использовать ООП или процедуры.

> Стоит реже компилировать свой код, вообще стоит больше писать меньше собирать.

Лисперы негодуют. Написал функцию — ткнул C-c C-c. Что в этом плохого?
Вроде на топик зла не похоже. Так в чём же возражения, анонимный минусатор? Не бойся, рот откроешь — язык здесь не откусят.
>>До того как сесть что-то писать, вы должны более менее представлять как это все будет работать

>Автор — фанат водопадной модели?


А что, при agile подходе проектировать не нужно? Вот ведь новости какие…

Waterfall, scrum и прочие умные слова — это подоходы к организации процесса разработки. «Более-менее представлять, как это всё будет работать» нужно в любом случае.

К примеру, у нас сейчас исповедуется классический скрам. Полный фарш: sprint planning, task estimates, developers' capacity, daily stand-ups, burn-down chart, demo, retrospective и далее по списку (извините, не знаю русского перевода терминов). При этом весь первый («нулевой», как мы его называем) спринт был посвящён проектированию и концептам. И уже теперь, когда мы точно знаем, какова общая архитектура проекта в целом и каким образом модули будут взаимодействовать друг с другом, мы начинаем последовательно реализовывать фичи, выкатывая «demo-able» продукт в конце каждого спринта.
А как же комментарии… комментарии к коду? Хорошо документированный код не только помогает понять ИДЕЮ первоначального разработчика, но и полезен ему самому. «Хочешь понять сам — объясни другому»
Действительно забыл написать про комментарии. Это вообще отдельная тема для меня, ибо я считаю, что комментариев в коде быть не должно. Если надо объяснять «что» делает код это большая проблема этого кода. Комментарии нужны только для того, чтоб объяснить «почему» код делает именно это и именно так. Тоесть либо это странный и сложный функционал который он реализует, либо обходятся какие проблемы какого-то апи, какая-то хитрая оптимизация, либо какая-то другая форс мажорная ситуация.
Вы, наверное, только на маленьких проектах работаете?

В больших проектах отсутствие комментариев — это мрак. Да, можно, конечно, покопавшись в коде, в конце концов разобраться что к чему, но, поверьте, в больших проектов и без этого есть чем голову занять и на что время тратить и лишние траты ресурсов (времени, мозгов, нервов и т.д.) там совсем ни к чему.
Сейчас да, работаю с относительно небольшими проектами, но до этого у меня был проект имевший следующие масштабы: 6 лет разработки и поддержки (коммандой 5-7 человек), 40 проектов в решении (не считая мелочи всякой), 32Мб в исходниках. Это достаточно не маленький проект.
И те исходники были без комментариев? Ужас!

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

1. Пока алгоритм полностью не меняется (что бывает, конечно, но достаточно редко) переписывать комментарии практически не приходится. Небольшие изменения вообще не требуют замены комментариев. Т.е. в целом затраты времени стремятся к нулю.
Более того, т.к. комментарии часто пишутся еще на стадии проектирования алгоритма, то они дают не затраты, а огромную экономию(!) времени. Сколько раз наши молодые программисты наступали на грабли, сразу начиная писать код, не попытавшись изложить всю последовательность действий, которая потом становится отличнейшим комментарием!

2. При сопровождении кода не раз лично сталкивался с ситуацией, когда отсутствие комментариев стоило пары дней копания в коде, чтобы «разложить всё по полочкам». Написать комментарии в момент обдумывания кода — это тьфу! А потом сколько времени экономит!

3. Сам не раз сталкивался с ситуацией, когда глядя на код, который требовалось дополнить/изменить, говорил: «Неправильный код. Можно сделать и короче, и быстрее, и удобнее для сопровождения». После переделки вдруг оказывалось, что выбор «неоптимального» варианта не зря был сделан — есть подводные камни, но программист, увы, их не описал в комментариях.

Это я только навскидку вспомнил. Покопавшись, я могу привести еще много разных примеров, как от отсутствия комментариев мы теряли время.

Вывод по итогам нашего проекта: соотношение времени, затраченного на комментарии, к времени, сэкономленному с помощью комментариев, наверное, где-то 1:100. Хотя могу ошибиться в меньшую сторону.

Вообще говоря, нормальные комментарии — один из факторов, который сейчас позволяет 1.5 оставшимся программистам (я себя считаю за половинку) не только успешно сопровождать более 250 тысяч строк кода (время нахождения и исправления ошибки — максимум 2 часа, обычно — до получаса), но и заниматься программированием дополнительных модулей в этот проект.
Не спорю, комментарии нужны, особенно в неоднозначных кусках.
Но хорошо написанный код, сам себя документирует.
Всё же короткое описание «что делает», а не «как», особенно в стиле javadoc\phpdoc здорово помогает, а в случае с php (и, возможно, другими динамическими языками) помогает IDE давать интеллисенс подсказки.
пока автор не начал писать как любит писать именно он все было тривиально, но правильно и хорошо.
Занятное чтиво для конца рабочего дня :)
В моей команде вы бы задержались до первого code review. Я не претендую на совершенного (или очень хорошего) кодера, но мои понятия о вменяемом (даже не хорошем) коде не соответствуют вашим рекомендациям про I,k,f, отсутствие коментариев и.т.д.
Извините, не затруднит изложить свои понятия по пунктикам?
Честно говоря полностью излагать свои понятия, да, затруднит. Тем более я не претендую на идеальный код, в отличии от автора статьи. По поводу тезисов автора:
— Как минимум «читабельные», емкие и понятные названия классов, методов и ПЕРЕМЕННЫХ. i, j еще можно понять в простейшем цикле в качестве счетчика, но не более того.
— Комментарии необходимы, особенно при работе в команде. Отношение — джуниоры и так ничего не поймут считаю дешевыми понтами человека, которому в лом написать пару строчек комментариев.
Думаю еси вам придется читать чужой код полностью без комментариев и с однобуквенными переменными вы за голову схватитесь.
— «в качестве счетчика» — и можно расширить на другой очевидный контекст, налагаемый единичным оператором (да, глупо называть переменную bln или tmp).

— в комментариях тоже должен быть минимализм. Чаще всего не хватает информации, не что делает комментируемая единица (метод\класс\пакет), а как она вписывается в общую схему, какая идея реализована, и где используется и как обращаться с ней. Ну, если алгоритм сложен и неочевиден, неплохо бы тоже написать пару слов, что бы, если код написан плохо, хороший программист, не считая код магией, мог бы эту единицу переписать по-своему.
Я ценю ваше стремление защитить автора. Я бы никакой критики не написать, если-бы он просто выложил свой код в статье без претензии на его (кода) грамотность и читаемость. НО, автор по сути учит читателя как писать. И я считаю некоторые рекомендации в корне неверными. И как видно, многие из комментаторов согласны со мной.
Я понимаю, что вы хотите оправдать пассаж автора про названия переменных, приведя примеры, где такие названия оправданы, но:
> Я так же стремлюсь *всегда давать очень короткие имена* переменным i,d,v,k
Тут не сказано ничего про счетчики. зная, что русский у автора родной, я понимаю словосочетание «стремлюсь всегда» вполне однозначно и не пытаюсь ничего домыслить.

По каментариям то-же самое. Было сказано, что автор их *никогда* не использует. Я далеко не все комментирую и против подхода «3 строки комментов, одна — кода», но во многих ситуациях комментарии помогают другому программисту разобраться в коже за много меньшее время. Да и вам, если вы откроете код через год.
> Тут не сказано ничего про счетчики
И правда, можно сказать, что у него в зоне видимости не может быть более 26 переменных…

> По каментариям то-же самое
Точно. Я и сам грешу тем, что в своих проектах не пишу ни строчки комментариев…
А вообще мне было бы интересно, задержался ли бы я в вашей команде ))))
Вполне возможно, что и задержался бы, видно что человек не глупый, просто у него немного другие взгляды. Гдето бы поругался пару раз и все бы свыклись :)
Кстати, насчёт взглядов. Думаю, правильно, когда заставляют конфигить IDE на единый стиль кода. Правда, вначале ужасно трудно переучиваться
Автоматическое форматирование, конечно, помогает, но не во всем, увы.
Некоторые вещи после автоформатрования приходится доформатировать ручками, ибо иначе плохо читается.
Вряд-ли. У моих инженеров специфическая сфера деятельности, где кодинг занимает максимум 30% времени.
На мои способности менеджера вроде никто не жалуется и у нас очень дружная (насколько оно может быть в культурном контексте азии) команда. Не знаю, что в моем тексте заставило вас усомниться в моей компетентности.
Да нет, я не сомневаюсь, я сам прицениваюсь, стоит ли мне над своим стилем кода работать или сойдет )
В общем случае, над собой стоит работать всегда :)
Чтобы не было недоразумений, «вряд-ли» не потому, что я сомневаюсь в ваших способностях. Просто род деятельности требует некоторых знаний индустрии + достаточно скучен для «настоящих» программистов.
Могу показать пример кода (довольно большой!), где нет ни единой строчки комментариев, однако он очень хорошо читается.
>В моей команде вы бы задержались до первого code review.

Т.е. ваша команда не готова обучать, вам сразу подавай профессионала, полностью разделяющего принятые в команде принципы?

Code review нужны в том числе для обучения и повышения квалификации, причём они чрезвычайно эффективны в этом плане. И ревьюировать должны не только «старшие» «младших» (чтобы явно указать на огрехи), но и наоборот (чтобы молодые «цепляли» от более опытных товарищей хорошие подходы и приёмы, плюс смотрели, какие замечания оставляют другие, более опытные ревьюеры).
Я не готов обучать человека, который настолько уверен в своей правоте.
Человек считает себя состоявшимся специалистом, более того считает что хороший код умеют писать «только единицы», включая автора. Это он будет всех учить на работе, поэтому да, такие люди нам не нужны :)
И на последок еще несколько замечаний
граммар наци негодует
В избранное!

Впрочем, можно добавить ещё парочку полезных советов:

Use BDD
Все свои (или чужие) хотелки и идеи пишите не только на бумаге, а оформляйте как код, и пусть это будут тесты для ещё не написанных классов\модулей. Этим вы конкретизируете себе задачу, а тесты будут вас направлять, если вы сбились с пути — т.е. они применимы ко всем пунктам статьи. Я уже не говорю о том, что у вас будет «пуленепробиваемый» код (конечно, при грамотных и очень разнообразных тестах)

От простого к простому
НЕ ставьте больших задач, разбивайте их на малые, и тестируйте. Потом «собрать» приложение как конструктор в сложную логику тоже окажется простой задачей. Имеет смысл выделить приоритетные функции — чтобы показать, что работает впринципе, а навороты и удобство потом. Всё подкрепляйте тестами.

Разделяй и властвуй
Отдельный модуль должен выполнять только строго определённую задачу. Если задача неделима, но находится в пересечении функции существующих модулей — возможно, стоит сделать отдельный модуль. Модули должны быть минимально зависимы друг от друга, что бы можно было выкинуть любой модуль, остальные же части приложения должны работать (возможно, вместо выкинутого модуля можно поставить заглушку). И наоборот, что бы можно было поднять и протестировать отдельный модуль без поднятия остальных.
Здесь помощники: DI, IoC, EDD, MVC

не согласен по поводу «Стоит реже компилировать свой код, вообще стоит больше писать меньше собирать.»:
Доверяй, но проверяй
Все мы люди, и не стоит доверять даже себе. «На бумаге» легко не заметить ошибку «на единицу», других условий… Поэтому, как только написал функцию или код — запусти, посмотри, работает ли, и работает ли как надо. Внешние с точки зрения модуля(именно модуля, не только аппликации) данные должны проверяться на допустимость (тип, наличие, размер и т.д.).
Эти проверки можно отрубить в продакшене, если действительно виден выигрыш в производительности.
Если придерживаться BDD, то оно получается само. Идеальный случай — если аппликация может работать в фоне и «подхватывать» изменения сразу же, без перезапуска (интерпретируемые языки, типа PHP, Perl, Python,Rubt могут это позволить, для Java стоит написать собственный ClassLoader). А ещё идеальнее, если бы сразу срабатывали и тесты.

И о документации
Я не люблю писать документацию, и часто игнорирую этот пункт. Но хотя бы код должен быть понятным. Чаще достаточно просто коротких и ёмких имён.
«От простого к простому
НЕ ставьте больших задач, разбивайте их на малые, и тестируйте. Потом «собрать» приложение как конструктор в сложную логику тоже окажется простой задачей.»
Возвращаемся к МакКоннелу и (подробно) описанной у него проблеме выбора между top-down design и bottom-up design. Вы предлагаете исключительно bottom-up и неизбежно получите все его проблемы — например, тот факт, что каждая мелкая задача по отдельности работает, а вот вместе не связывается, потому что архитектура неправильная.
> Вы предлагаете исключительно bottom-up
Нет. Проектировать надо сверху-вниз (от абстрактных идей до реализации), а вот реализовывать предлагаю снизу-вверх. Чтобы связывалось вместе, тоже есть тесты :)
Для того, чтобы проектировать сверху вниз, надо ставить большие задачи.
Конечно, если бросаться реализовывать мелочи, можно упустить цель приложение, и получить вообще несобираемое. Нужно иметь представление о приложении в целом, и о том, какие цели какой модуль решает, но кодировать нужно не монолит.
Спроектировали сверху-вниз, ага, кодим отдельные части, иногда посматривая на приложение «с высоты птичьего полёта» — но при конкретно кодинге внимание нельзя рассеивать.
… а это называется Information hiding. У того же МакКоннела.
Вы так говорите, как буд-то это что-то плохое :)
Просто это не то, что вы написали выше.
Да, пишу я не очень, кодирую, надеюсь, получше :)
По поводу длины имен.
Не помню, кто сказал:

Длина имени должна быть прямо пропорциональна размерам области видимости.
>> Я так же стремлюсь всегда давать очень короткие имена переменным i,d,v,k

Хотел было поспорить, но потом вспомнил, что, скажем, на Haskell, зачастую именно так и пишут. Наверное, просто следует сделать особый акцент на длину методов/фукнций, их имена и количество переменных/аргументов. Если метод состоит из 3-5-и строк, где в основном вызываются другие методы (с хорошими именами) и локальных переменных с аргументами в сумме пять штук, то нет ничего плохого, чтобы назвать переменные y, m, d. Но если честно, с трудом вериться, что кто-то так пишет на С#.
Также я всегда использую var никогда не использую явное типизирование (ну только когда выхода нет). Я так же стремлюсь всегда давать очень короткие имена переменным i,d,v,k для меня не проблема, ибо функции маленькие все понятно из контекста. Зачем писать currentNode если можно написать просто n и при это все равно все ясно?

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

Что же касается имен переменных, то «всё ясно» исключительно в случае коротких методов, только автору и только вскоре после написания. А если мне нужно залезть, скажем, в вычисление интереса на банковском счету и кое-что поправить, то мне будет куда проще это делать, если переменная называется «lastMonthInterest».

Однако стоит по возможности стараться все делать как можно проще.
Я бы сказал, не «проще» а «понятнее». Выражение «i = 0 — i» очень простое, но понять, что оно используется для того, чтобы присвоить i единицу, если там был 0, и 0, если там была единица, удается не сразу. (Предположим, что мы уверены, что в этом месте кода i гарантированно равняется или нулю или единице).
>Выражение «i = 0 — i» очень простое, но понять, что оно используется для того, чтобы присвоить i единицу, если там был 0, и 0, если там была единица, удается не сразу.

Скорее всего, вы хотели написать «i = 1 — i», я правильно понял?
Ну да, именно :) Спасибо за поправку.
> Также я всегда использую var никогда не использую явное типизирование (ну только когда выхода нет).
убил бы!
Да почему ж ) мне лично симпатизирует подход с выводом типов, когда не нужно их везде описывать, где можно понять из контекста. Однако при это необходима строгая типизация, чтобы при двусмысленном результате требовалось явное типизирование. Тогда проблем не будет, только плюсы.
Выше уже аргументировали, чем плохи «очень короткие имена переменным».

Хочу постараться аргументировать, почему «всегда использую var» тоже скорее вредный совет, чем полезный.

Представьте, вы читаете код:

var product = ReadProduct(...);

Что возвращается в это методе? Как посмотреть что-то в типе?
Приходится идти в объявление метода, а оттуда — в обявление возвращаемого типа.
Не говоря уже о том, что без студии такой код вообще сложно понять.
А если в методе пяток таких переменных (да еще с именами i, d, b, k) — вообще не завидую тому, кто будет пытаться это прочитать.

Сравните:

ProductData product = new ProductData(...);

Во-первых, сразу видно, какой-тип возвращается.
Во-вторых, с этого же места можно сделать «Go to Declaration» на типе и узнать про него, все что нужно.

Поскольку сам неоднократно сталкивался с этой проблемой, на данный момент выработалась некая практика.
Вот примерный список ситуаций, в которых, на мой взгляд, оправданно использовать var:

1. Характер выражения позволяет сразу определить возвращаемый тип (например, конструктор).

var product = new ProductData();


2. Объявление типа настолько громоздко, что и упоминать его лишний раз не хочется (хотя еще вопрос, зачем возвращать такие типы — но иногда бывает, что это внешний интерфейс который нельзя поменять).

Dictionary<int, List<Tuple<int, string, string>> ReadComplexData()
{
     ...
}

...
var complexData = ReadComplexData(...);


3. В объявлении foreach-цикла (мне не очень нравится по изложенным выше причинам, но в целом считаю вполне допустимым).

foreach (var product in allProducts)
{
     ...
}


4. В LINQ выражениях. Здесь плюсы от var перевешивают минусы — слишком уж удобно комбинировать различные выражения и менять их содержимое.

var allProducts = ReadOrders(...)
     .Where(order => order.Date < data)
     .Select(order => order.Product);

var relatedDescriptions = allProducts
     .SelectMany(product => GetRelatedProducts(product))
     .Select(related => related.Description);

У меня правила такие (кроме определений где используются generics, но там без var никак):
1) Для value типов var не используется никогда. Иначе легко пропустить преобразование типов, потерю точности и т.д.

2) Если правая часть содержит явное указание типа, то var обязателен.

3) В foreach блоках если важен лишь интерфейс, то используется var, если конкретный тип то он указывается явно.

4) Если есть достаточно явное стремление к duck-typing (например вам просто важно, что у объекта можно вызвать некий метод Method(), то используется var даже если тип неочевиден. Особенно полезно применять это правило при написании тестов, в которых вам впринципе не важно, какой тип вернулся, важно лишь что в нем присутствуют нужные методы\свойства.
«Что возвращается в это методе?»
Прочитанный продукт. Этого достаточно, чтобы понимать читаемое.

Читайте Липперта, у него описано, как, зачем и почему можно использовать var, и разница между семантикой переменной и типом переменной.

«Как посмотреть что-то в типе?»
F12 на var. Или Go to declaration в контекстном меню.

(а вот сочетание var с бессмысленным именем переменной, очевидно, противопоказано)
В том что на var можно выполнить «Go to Declaration», вы безусловно правы.

Но что, если это будет метод ReadProducts(), который возвращает List<ProductData>?
«Go to Declaration» на var приведет меня в List<T> (и на практике я слишком часто с этим сталкивался, чтобы отбить привычку употреблять var где попало).

Может есть какие-то неизвестные мне трюки для студии?
Есть ли способ попасть в тип ProductData в этом случае?

А приведенные мной примеры, конечно, не претендуют на полноту. HeavyWave привел несколько ситуаций, в которых я тоже использую var.

Я лишь хотел обосновать позицию, что var вовсе не следует использовать везде, где это возможно. Но мне кажется, что с этим вы и без меня согласны :)
Если честно, я таких трюков не знаю просто потому, что мне эта задача никогда не приходит в голову. Мне почему-то очень редко нужно лезть в описание типа, возвращаемого другим методом.

«Я лишь хотел обосновать позицию, что var вовсе не следует использовать везде, где это возможно.»
Просто у нас с вами разное понимание «возможности».

С другой стороны, повторюсь, у Липперта это описано более чем подробно, не вижу особого смысла повторять здесь его статью.
Рекомендую по теме почитать про паттерны реализации.
Также я всегда использую var никогда не использую явное типизирование

А я бы за такое руки оторвал. В некоторых языках(as3 например) это приводит к существенному снижению производительности. Это раз. Во вторых это сводит самодокументирование кода к нулю.
Sign up to leave a comment.

Articles