Pull to refresh

Comments 242

я всегда пишу тип переменной в её названии.

LONG m_longForSomeHren;
BYTE m_byteSomeByte;

m — member
l — local
lp — local pointer
mp — member pointer и т.д.


А то потом встретишь в коде authorHappiness — и сиди думай что это за переменная.
Спасибо за замечание. Я долго думал, включать этот пункт или нет.
Когда я писал только на Java, всё было просто: тип и видимость переменной подсказывала IDE. Однако, при составлении программ на C-подобных языках, иногда без IDE вообще, понял, что без m_ очень сложно.
а как называется шрифт исходника, который ты привел?
спасибо, надо скачать, а то под виндой его не нашел =(
UFO just landed and posted this here
попрыгав через go to definition у меня может и мысль пропасть — меня наоборот это отвлекает.
UFO just landed and posted this here
на вкус и цвет, переменную объявлять там где она используется, а не за три-девять земель! )
UFO just landed and posted this here
Думаю что всё-таки нужно хорошо проектировать классы.
Большое количество статических переменных — косвенный признак плохой архитектуры классов.
Хотя конечно зависит от задачи…

Ну если вам не повезло — IDE вам в руки, и спецификации. :)
UFO just landed and posted this here
Тогда это действительно превратится в муку, если у вас склероз на эти несколько переменных.
UFO just landed and posted this here
правильно. можно вспомнить за 5 минут, поработать два дня и забыть на пол года.
«на вкус и цвет фломастеры разные»

p.s. извините, не удержался.
Зато когда вы решите сменить тип переменной с int на unsigned long int вам не придется судорожно скакать по коду и менять ее имя везде где она встречается.
А если вы, не дай бог, забудете этого когда-нибудь сделать, следующий кто будет работать с вашим кодом получит неверную информацию о переменной, ИМХО Вы перекладываете на свои плечи (плечи программиста) работу IDE, уже давно все приличные IDE показывают тип переменной в ToolTop'е
любой IDE сам всё мне переименует, я же не в блокноте пишу (хотя и там есть Ctrl+H).
любая нормальная IDE покажет тип переменной.
для того чтобы его увидеть надо совершить какие-то действия, ну как минимум курсор навести. А когда голова занята написанием алгоритма сложнее открытия файла(к примеру) — любые лишние телодвижения отвлекают. ну ненравится вам так — пишите по своему, я же не заставляю.
а зачем вам нужно знать тип переменной?
если вы пишете на ПХП — то не надо. А если на С++, то можете вместо переменной записать половину переменной. Недавно в рассылке дебиана видел =)

size_t n;
fscanf(f, "%u", &n);
if ((n > K_MAX_ITEMS) || (n == 0))

человек объявил size_t переменную, которая на АМД64 занимает 64бита, а потом читает в нее fscenf, но как в unsigned int, которая 32, в итоге очень удивлялся почему условие не срабатывает. Так что если вы не на пхп, тип переменной учитывать крайне важно.
это банальная невнимательность, в пхп тоже можно каутн от строки взять и удивляться почему резуьтат всегда 1… дело не в приставках, а если вы пишете «алгоритм сложнее открытия файла», то его можно писать и без типов переменных, в википедии все алгоритмы написаны на «гипотетическом языке» и нормально функционируют, и 99% из них сложней чем «открытие файла»
опечатка=) каутн = count подсчет элементов в массиве, на строках всегда возвращает 1
я ответил на вопрос «зачем нужно знать тип переменной», но с именованием в этой ветке я при этом согласен быть не обязан. Вы же мне эти заслуги приписали.

Но с другой стороны, есть ru.wikipedia.org/wiki/Венгерская_нотация которая данный синтаксис как раз таки и пропагандирует по большей части и вот с ней надо считаться.
да и если в коде надо типы менять, это я считаю ошибкой проектирования.
Вы никогда не совершаете ошибок?
конечно совершаю. наверняка больше вас, так как я не то чтобы совсем програмист. но написав кучу кода используя переменную, потом осознать что она не того типа — это уж крайне редкая ситуация.
эм, банально изменились требования и необходимо поддежривать 64-битные числа вместо 32-битных?
что то сломается если переименовать?
когда переменные нормально названы то никаких проблем быть не должно. если какие-то стандартные имена типа l_dwordIndex, так они в прямой видимости(на одно-двух страницах кода) находятся.
Это легко может произойти, скажем, если поменялся тип данных, передаваемых объекту извне. А тот тип, с свою очередь, может измениться по независящим от разработчиков причинам. Например, перестало хватать простого инта и пришлось использовать что-то более длинное. Или срочно понадобился знак там, где его не предполагалось использовать.
без личностей, я совершаю достаточно ошибок (и уж, если откровенно как раз больше вас, именно потому, что я совсем программист, в смысле профессия это моя), просто я считаю, что совершение ошибок это нормальный рабочий процесс, как говориться не ошибается только тот, кто ничего не делает.
вы ждёте что я вам возражать буду? нет, не буду. всё правильно.
может из за того что я очень медленно пишу, именно таких ошибок у меня почти не бывает.

строго говоря, он прав, для того и придумали agile техники, чтобы ошибки проектирования стоили меньше крови.
такую детализацию лучше не использовать. Достаточно указать char, string, number. Все остальное сложные типы. если размерность с short на long еще возможна для одной и той же переменной, то с string на int — врядли. Скорее всего прийдется изменить и наименование.
Напрасно. Если это будет не `authorHappiness`, а `lpcwstrAuthorHappiness`, станет легче?
1. Особенно «удобно» произносить такие переменные, объясняя по телефону/скайпу, например `m_lpctstrzShortName`. Пипец, хоть СМС пиши.
2. Если использование переменной и ее объявление не умещаются на одном экране, у вас имхо слишком длинный метод.
3. Goto declaration есть в любой IDE. Если вы пользуетесь блокнотом или другой «смотрелкой», см. пункт 2.
да, lpcwstrAuthorHappiness для меня легче. правда я напишу lp_strAuthorHappiness.

1. я никому не говорю имена переменных
2. кому как
3. меня это отвлекает
1. вы еще не работали в команде.
2. тут скорее когда как
3. а зря… в современных иде много полезных фич, которые позволяют избавиться от ужасного winapi подобного стиля именования аля lpcwstr…
1. и не собираюсь
2.…
3. я ими пользуюсь когда мне удобно
1. А зря, сейчас такое время, когда один человек не в состоянии написать хоть сколько-нибудь крупное коммерческое приложение, работа в команде это один из ключевых скиллов программиста при устройстве на работу в компании, единоличников не любит никто.
В прочем, глянул ваш ранний пост, то что я написал не про Вас, у Вас свой бизнес, но вообще программистам командная работа нужна.
я и не отрицаю того что работа в команде касается 90% а то и более програмистов. но только тут будут играть общие правила которые примет команда. можно их сколько убеждать что и кому удобнее, как команда решит так и придётся писать.
Этот «ужасный winapi подобный стиль» называется «Венгерская нотация», а использовать её или не использовать это уже личное дело каждого разработчика. И не нужно приплетать сюда работу в команде, как ни крути, одна команда написала целую операционку с использованием такого стиля и говорят, довольно успешную.
А IDE не все используют и не везде.
Да про IDE согласен, слышал те самые кодеры которые написали ту самую операционку юзают блокноты. Тут в общем кто как хочет.

А про «Венгерскую нотацию» хочу сказать, что я, как человек начавший кодить уже в дружелюбном .NET, и только потом копнувший глубже в winapi мол «а как оно там все интересно работает?», признаю, что это может и удобно, но поскольку тема про читаемый код, то согласитесь… читается то оно как раз плохо.
я как человек начавший кодить много раньше, скажу что мне понятнее так как я описал.

Мне ненадо никуда смотреть кроме кода. Ненадо никуда двигать мышью чтобы узнать тип и переменные у меня имеют осмысленные и длинные названия, префикс это не всё. Когда я смотрю на свой код — я вижу как оно работает, и не заставляю свой мозг искать ненужные и отвлекающие вещи.
я всегда писал в юниксовой традиции, где, конечно, встречаются cryptic names, но они весьма осмысленны и обычно используют некое негласное общее соглашение, венгерская нотация же считается неприличием.

больше всего, опять же, писал на динамических языках, хотя начинал с С/C++.

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

не получается ли некоторая избыточность? тем более, если речь идет о де факто стандартном в промышленном программировании test driven development, когда каждая функция обвешивается тестами и опробывается в таком окружении, что ложные аргументы передать просто почти невозможно.

да и в случае с++ редко приходится работать чисто с нативными типами, чаще это объекты, полную запись класса которых писать явно не стоит.
я уже незнаю сколько раз это писал — конкретно мне так не удубно. даже по одному экрану бегать глазами. могу такую аналогию привести:

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

я даже прямо спрошу — вам такая нотация мешает чем-то кроме того что её считают неприличной?
мне она кажется некрасивой :) в инженерном смысле — несколько избыточной. Мне всегда хочется сделать код предельно лаконичным, даже в смысле названий. Хотя, конечно, может сказываться профессиональный опыт.

Вы, должно быть, под винду писали?
а вот мне наоборот. я например с большей вероятностью назову класс CEConnectionSocketToFile чем СConnStoF ну и т.д.

последние 12 лет виндовс(обычная + мобильная немного). до этого asm z80. сейчас вот Javascript смотрю, вот в нём конечно это избыточность.

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

И все эти памятки они для тех кто ещё не знает как лучше и пробует.
ну… Это ж тема из ряда классических холиворов, плюс еще накладывается местами вечный linux vs windows :)) в принципе пофиг, дело вкуса.

я вот бы вообще не так писал. Раз уж мы знаем контекст места, и тестируем функцию, то при должном количестве комментов в районе объявления достаточно обойтись названием вроде простого «socket» или, если совсем уж короткая функция и сетевой API внятный — «s». В конце концов, там сверху будет открываться этот самый сокет к файлу и, раз уж мы пишем так, как книгу писатель бы писал, получится что-то вроде:

s = connection(file, ...args)
s.write(data)
....
s.close()


Это, кстати Питон, но на Си я бы так же писал. Зачем повторяться и многократно повторять одну и ту же информацию?
>такая нотация мешает чем-то кроме того что её считают неприличной?
Скажу за себя. Некрасиво и избыточно. Продираться через все эти lpcwstr на каждой букве глаз спотыкается, а мозг силится понять чего же это такое и выстроить последовательность в тип. Отвлекает жутко.
Постоянно смотреть на то какой у переменной тип нужды нет. Если работаешь с каким-то куском кода и забыл тип переменной, то либо выбрана не та профессия :), либо дизайн программы настолько ужасен, что во всё этом можно запутаться.
Венгерская нотация бывает системной и для приложений. Изначально она была использована с ms word для того чтобы отличать переменные, ортогональные по смыслу, никак не по типу. Моду на lpcwstrYetAnother в winapi взяли на вооружение позднее.
Подробнее: Как заставить неправильный код выглядеть неправильно.
ага, помню эту статью

Разработчики winapi вообще много чего взяли на вооружение довольно странного. Мой любимый момент это функции с десятком аргументов, каждый из которых — это типа одна из констант с названием типа BLABLABLASENUMSCNST :)

WYSIWYG, чего уж там.
Так напишите для вашей IDE плагин, который будет выдавать декларейшен при наведении мыши.
В Visual Studio это вообще сделано с самого начала, есть бесплатная Visual Studio Express.
с незапамятных времён пользуюсь VisualAssist'om, он всё это делает.
Да, лень великое дело…

Взять, да и свалить все на ИДЕ.

«Компьютер должен работать, человек думать» ©
Это верный признак того, что функция получилась слишком длинная. Ну или используется много глобальных переменных, что ещё хуже.
Венгерская нотация для простых типов конечно хороша, но что делать для пользовательских? Например, как будет выглядеть экземпляр переменной класса CUnboundException, SimpleCreatureFactory и подобных?
у всех моих классов префикс CEClassName, объекты соответственно m_ceObject, l_ceObject…
Ну и какой толк от этого? Все переменные всех классов имеют один и тот же префикс, где логика? Как по переменной m_ceObject можно понять какого она класса?
как минимум понятно что это объект. есть другие варианты?
В том-то и дело, что никаких. Как я уже сказал, венгерская нотация хороша для простых типов, но пасует перед пользовательскими. Посмотрите в код Win32 API либо MFC, для примера, как там микрософт изголяется.
это же не отменяет её полезности для простых типов. код мс и так частенько смотрю ;)
Я добавляю префикс in перед входными переменными, т.е. так:
foo(int inNumber)
>>встретишь в коде authorHappiness — и сиди думай что это за переменная
Я в шоке 0_0 Как можно юзать переменную, если не знаешь ее тип и предназначение…
А если в проекте >100 классов? И пишется он не один год, всё помните? я не помню, может у меня под это мозги не заточены. поэтому пишу тип переменной и во время написания кода на вознью мышкой не отвлекаюсь, иначе ещё медленней буду писать.
>А если в проекте >100 классов?
Значит вы не знакомы с одной из основ ОО-дизайна — инкапсуляцией :).
У вас в коде разве есть место, где используются все эти 100 классов? Тем более, вы же сами показали, что в случае переменных классов этот замореченый стиль не работает.
>И пишется он не один год, всё помните?
Зачем всё? Классы небольшие, связность классов маленькая, методы обозримые. Если у вас не так, значит вы что-то неправильно спроектировали. Когда вы что-то правите, код класса всё-равно перечитываете, чтобы логику понять.
что значит «встретишь». Она в воздухе будет висеть? или будет что-то вроде
authorHappiness +=1;
?
Если и по контесту непонятно, и из задачи неясно, как уже неоднократно заметили практически все современные IDE показывают тип в подсказке. Еще дельфи с незапамятных времен умела.
Это называется «венгерская нотация».
Я не так много пишу на cpp, но мне кажется, что хорош вариант использования нижних подчеркиваний для приватных членов класса.
Например:

private:
int __count;
protected:
int _max;

Правда, это в некоторой степени питонизм, но я в основном пишу на питоне, и мне кажется это вполне логичным.
Я не так много пишу на cpp, но мне кажется, что хорош вариант использования нижних подчеркиваний для приватных членов класса и двойных нижних подчёркиваний для параметров функций.
Например:

private _count:int;
protected _max:int;

function countIsMax(__count:int, __max:int):Boolean
{
return (__count == __max);
}

function set count(__count:int):void
{
_count = __count;
trace(«count updated: » + count);
}

if (countIsMax(_count, _max)) count = 0;

Но я в основном пишу на Action script, и мне кажется это вполне логичным.

Бардак )
Я вам дам совет НИКОГДА не называйте переменные с двойным подчёркиванием когда пишете на С/С++. Эти имена зарезервированы для разработчиков компилятора. Вы можете использовать их на свой страх и риск, но в любой нормальной компании во первых дадут железной линейкой по рукам, а во вторых вероятность получить неприятный эффект отлична от нуля.
Во вторых, каждый язык програмирования имеет свой свод неписанных правил и идиом, и не стоит переносить их с одного языка в другой, Python язык динамический, у него нет явного указания private области видимости, потому используется такой вот узаконенный хак.
ok, спасибо, это код AS3 — там таких ограничений нет.
В языках со строгой статической типизацией это совершенно излишне. А вот если типизация динамическая (PHP) или нестрогая (плюсы) — то бывает полезно.
полезно? тип переменной в названии? в Питоне или Руби? руки рубить, да розгами сечь за такое «полезно».

на динамических языках нормальные системы без тестового покрытия >=90% не пишутся. Функции да методы ма-а-а-аленькие. названия переменных осмысленные и короткие. Код читаться должен как книга, иначе нафиг такой язык высоченного уровня.

а не… lptrlwSocket
Бывает полезно рисовать схемки классов и их взаимодействий. Имхо часто можно обойтись без UML.
Скажем комментарии в коде описывают колесо и все его функции. Часто нужно понять где и зачем это колесо используется. А так же зачем, скажем, нужны 2-3 разновидности колес.
Дополню: иногда приходится писать UI-компоненты. Тогда в заголовке файла с панелькой я обычно рисую схему панельки. Вот так:
+--------------------+
|    LBL:            |
|        /FIELD/     |
|             BTN/   |
+--------------------+
Кроме того, в п.2 упоминается C/C++ хидер, а код — Java ;)
CommonUtils — как-бы намёк на название класса с кучей статических методов :)
Предпочитаю писать комментарии на русском. Если разработку ведёт интернациональный коллектив, то английский, конечно, неизбежен. Но если реальной необходимости в этом нет, по-русски всё-таки проще. Даже если в правильности и ясности своего английского я уверен, не всем коллегам доверил бы чтение англоязычных комментариев :) C++ и Perl поймут лучше :) Да и для описания некоторых тонкостей программы гибкость русского языка очень важна.
Как раз сейчас разбираюсь с сайтом, в котором половина полей и ключей в базе данных, а также часть коментов, используют всю гибкость норвежского языка. Так-как сам я его не знаю, то весьма весело
Повторюсь: если разработку ведёт интернациональный коллектив, то английский, конечно, неизбежен!
Если Вы делаете OpenSource приложение или библиотеку, Вы не можете знать программисту из какой страны потребуется Ваш код.
и чем же это противоречит тому, что говорит aralex?
А если я делаю программу с закрытыми исходниками? По-моему, лицензию автор не оговаривал ;)

Да для OpenSource-а комментарии на английском — это хороший тон. Бесспорно! Хотя, согласно GPL — никаких гарантий. В том числе, гарантий читабельности исходников :)
Иногда не известно, кому Ваш код отдадут после Вас… А ну как найдётся индус, готовый работать за еду?

На самом деле, ИМХО, конечно, если комментарий сложно сформулировать, значит проблема в структуре кода. Например, у нас принято комментировать только «грязные хаки» (без которых, к сожалению, иногда никак), а весь остальной код должен быть написан так, чтобы его можно было как книжку читать :). Я, естественно, имею в виду комментарии внутри кода, а не описание, например, входных параметров функций для *doc
а у меня в одной из либ комменты на китайском
На самом деле это очень спорный момент.
Однажды я работал с очень важным блоком когда, который был написан итальянским разработчиком. Комментов было очень много, но они были на итальянском. Ну и названия переменных и методов были на итальянском.
Моей задачей было переписать этот кусок «чтоб работало также». Scegli una lingua nuova :)
Ещё раз повторюсь: если разработку ведёт интернациональный коллектив, то английский, конечно, неизбежен. Но если реальной необходимости в этом нет… :)
Вот наверное испанец и норвег тоже считали, что реальной необходимости нет.
В случаях, когда пишется хоть чуток востребованная кем-то кроме тебя программа, никогда не знаешь, кто будет смотреть/поддерживать код. Поэтому, не только мой опыт подсказывает, что лучше с самого начала приучить себя писать коменты и именовать переменные на английском.

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

Вполне вероятно. И по-своему они правы: всегда приходится выбирать между общественно-полезным и удобным для себя лично. Если написание комментариев на иностранном языке создаёт серьёзные препятствия работе, то есть повод задуматься, ради чего Ты работаешь: ради удобства забугорных программистов (которые, может быть, когда-нибудь будут изучать твою программу) или ради быстро и качественно сделанной работы. Если участие иностранных разработчиков маловероятно, по-моему, стоит предпочесть родной язык.

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

Я не буду утверждать, что российским программистам нужно писать комментарии только на русском. Это должно определяться корпоративными стандартами компании. Если руководители решили, что английский актуален — на английском. А мы пишем на русском. Потому что так проще, понятнее, и привлекать к работе иностранцев мы не планируем.
Давно как-то читал исследование буржуев про комментарии в программном коде. Они нам очень завидовали — русские графемы отличаются от латинских и комментарии сразу хорошо видно — они не сливаются с текстом программы.
Впрочем, это было в те времена, когда небыло не то что IDE с подсветкой синтаксиса, но даже цветных мониторов :). Сейчас подсветка эту проблему решает.
Кроме комментариев к коду есть еще комментарии к коммитам, с ними та же история. Если зарубежных разработчиков нет и не планируется, то лучше грамотный русский, чем обрывки безграмотного английского. Почему-то нечасто встречаю, чтобы разработчики комментарии к коммитам по-русски писали, имеет смысл делать это значительно чаще, не нужно этого бояться.
> лучше грамотный русский, чем обрывки безграмотного английского

А ещё лучше — грамотный английский ;).

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

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

Из-за того, что их сложнее писать, они пишутся менее подробно и точно.

И при всем этом смысла-то писать их на английском особого нет очень часто. Я к тому, что лучше решение принимать осознанно, а не говорить по дефолту «комментарии к коммитом пишем на английском». У комментариев к коммитам на русском есть много плюсов.
Спорить не буду — зависит от специфики. Но, уверен, что, в любом случае, уровень владения языком у хорошего программиста должен быть достаточным для написания комментария к коммиту.
Да, согласен, уровень должен быть. Вопрос тут в том, что даже если уровень достаточен, усилия все равно требуются разные, и это приводит к снижению качества комментариев.
Ну… тут, видимо, вопрос в дисциплине. В том, может ли себя человек заставить три минуты потратить на формулировку, чтобы достаточное качество обеспечить. Коммиты же, думаю, не настолько часты, чтобы эти 3 минуты стали критичными.
зато есть дополнительный резон изучить английский! ;)
А что у вас семпл непоследователен — то внутри скобок вызова функции есть пробелы, то нету? Мне кажется, самое главное последовательность и неизменность, а как именно вы оформляете — это уже второстепенно
Последовтелен :)
Я стараюсь не ставить пробелы в конструкторах и ставить при вызове функций.

Однако, теперь, когда Вы заметили, действительно как-то странно выглядит. Спасибо за замечание.
Продолжаем. За такое оформление (лишние отступы) надо бить ногами:
postCount          += 1;
authorHappines +=… bla-bla…
Поясняю: добавится у вас еще одна строчка в низу, более длинная — будете переформатировать весь кусок. Что за фигня, может вам лучше в типографы пойти?
А научить IDE делать такие отступы реально?
А толку-то? Дело не в том, что надо руками что-то менять — дело в том, что потом в хистори системы управления версии остаются пометки, что в связи с такой-то таской (багом, еще чем-то) строки менялись, хотя реально их только для красоты правили: вы добавили одну, а поменяли еще две тока потому, что вашей левой ноге захотелось форматирования в столбик. Реальное заподло самому себе.
согласен.
просто я с такой проблемой ранее не сталкивался. Мне и в голову не приходило так форматировать. Некогда. Надо код писать :)
во многих если не всех сравнялках/мержилках текстовых файлов есть опция «игнорировать пробелы»
Вполне: есть программка Jindent, она такие штуки делать помогает.
Я всегда так форматирую. И переформатирую, когда добавляется строчка.
Думаю, это вопрос вкуса.
Как отметили выше, при использовании системы контроля версий этот вкус переходит во вредную привычку.
Очень хорошее, кстати, замечание. Задумался…
Дурная привычка — ковыряться в носу или смачно сплевывать на улице; коммитить не проходящий тесты код или не делать регулярный бэкап продакшн базы.

А это… вполне представляю ситуации, когда редактирование упрощается засчет таких фокусов, скажем, в очень симметричных кусках кода.
Про отсутствие закомментированного кода… Наверное, стоит различать код, готовый к продаже, и код в процессе разработки. Первый, конечно, рудиментов содержать не должен: дурной тон. Во втором, мне кажется, вкрапления (!) закомментированного кода вполне допустимы, пока они актуальны. Пока действительно не устарели и если действительно не мешают читать актуальный код.
Ну, естественно. Код в разработке, как рабочее место художника, загадочен и непонятен постороннему.
Для того, чтобы он не был загадочен и непонятен, используются остальные 7 правил :) А закомментированный код — это как набросок на холсте. Или краска на палитре. Дожидается своего часа. Или уходит.
В моей практике бывает, что в комментах пишутся куски кода, который заработает после закрытия пары-другой мелких тикетов (под которые не плодят отдельных бранчей), чтобы блюсти правило про «мастер в любой момент компилится, и если нужно релизится», а код мирно дожидается своего часа уже на нужном месте
А у Вас ни разу не было случая, когда такой код с «кусочками для себя» уходил в поставку? По-моему, если вы храните «сувенир на память» об этом замечательном алгоритме, который сейчас не нужен, а вот в будущем..., то хранить его стоит у себя на HD или в прошлых версиях в репозитарии. Есть такой антипаттерн даже. Bot anchor называется.
Использование стандартов кодирования и оформления. Можно использовать вариант как для конкретного языка или среды разработки, так и внутрифирменный, со своей спецификой. Главное, чтобы все разработчики в команде придерживались единых правил, иначе…
eclipse + ctrl + shift + f и любой код читаем

в любой компании есть старый софт, который писался когда компания дико быстро росла и никто не уделял внимание качеству кода ) так что только так.
Если бы это и комментарии разумные добавляло… и поля переименовывало…

То мы потеряли бы работу :(
Сижу, разглядываю листинг на Питоне. Отец, глянув издалека на монитор, спрашивает:
— Маяковского читаешь?
quote/406082
Для меня еще актуальный вопрос по форматированию скобок.
1. Если в условии одна из веток имеет скобки, то и вторая должна иметь скобки:
плохо:
if(var1>2){
var+=3;
var3-=2;
}else
var1*=5;
хорошо:
if(var1>2){
var+=3;
var3-=2;
}else{
var1*=5;
}

2. Скобки я предпочитаю размещать не с новой строки, а на той же что и операторы. Больше информации помещается на экране:
плохо:
if(var1>2)
{
var+=3;
var3-=2;
}
else
{
var1*=5;
}
хорошо:
if(var1>2){
var+=3;
var3-=2;
}else{
var1*=5;
}
По моему опыту, вопрос размещения скобок — один из самых больных при согласовании стандартов кодирования.
Аргумент «с новой строчки»:
По моему опыту, вопрос размещения скобок — один из самых больных при согласовании стандартов кодирования.

Аргумент «с новой строчки»: более очевидно, где тело ветки.

Аргумент «на той же строчке»: больше кода помещается.
Аргумент «с новой строчки»: экраны у нас давно не 800x600 и кода помещается заметно больше ;)

Вот ещё вспомнил неудобную вещь — ломание строк, как будто экран пикселей 300 по ширине, типа этого. Сама по себе конструкция полный ужас, а когда в три строки написана вообще дурдом.

// RegEnumValue to enumerate the values in the key
while (ERROR_SUCCESS == RegEnumValue(hkey,
dwIndex++, szValName, (cbValName = chDIMOF(szValName), &cbValName),
NULL, &dwType, bData, (cbData = chDIMOF(bData), &cbData))) {
Хороший код и читать весьма приятно, и даже кажется порой работает он лучше. :)
А мне не нравится когда слишком много комментариев. Зачем комментировать очевидные вещи? Только место занимать и внимание отвлекать.
Как в вашем примере комментарий к методу sendPost вида 'send the post to the server', название функции в данном случае говорит само за себя.
Или комментарии 'state vatiables' — это к чему? Для людей, не знакомых с языком? И зачем в комментарии писать то, что уже написано в названии переменной?
В общем, я бы в вашем примере количество комментариев сократил минимум вдвое :)
Очень интересные замечания.
Однако, есть несколько контраргументов.
Комментарии методов:
1. В комментариях методов стоит намекать на реализацию. В примере с sendPost указано, что будет совершен HTTP запрос. Это значит, например, что эту функцию не стоит вызывать из нити, которая отрисовывает интерфейс.
2. Иногда читаешь только комментарии. Допустим, надо понять что умеет делать класс. Если все методы имеют комментарий, то глазу проще искать синенькие блоки и читать только их. Безусловно, самый плохой случай, когда у части методов комментарий есть, а у части — нет.
3. Иногда надо создать Javadoc. Тогда хоть какой-нибудь комментарий лучше, чем никакой.

Комментарии полей: Обычно у класса есть ссылки на «родительские» объекты, объекты, которые класс контролирует и поля состояния. Мне нравится разделять эти группы и явно указывать, что, например, следующие поля будут постоянно меняться. Потом проще вспомнить, что к чему.
Вы меня, кажется, не поняли. Я не говорил, что комментарии это плохо и давайте ка лучше без них. Я имел в виду, что чрезмерное количество очевидных комментариев — зло.

1. Комментарии с описанием функции post и перечислением ее параметров — вещь нужная и правильная, но совершенно очевидный комментарий к методу sendPost — не нужен.
2. Тут, видимо, на вкус и цвет товарищей нет. Но по мне удобней читать сам код и, если что-то ну совсем уж непонятно — посмотреть в комментарий, если есть. По моему, совершенно очевидно, что postCount += и authorsHappiness += это инкременты этих самых переменных. И мне комментарий, о том, что это таки инкремент — не нужен.
3. Для javadoc достаточно описания самих функций и их переменных. Не обязательно в каждую строчку пихать по комменту :))

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

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

Конечо, для мелких классов или внутренних функций этого нет.
Главное потом удалять очевидные комментарии, чтобы другие (следующие) разработчики не мучились.
Комментарий о том, что делает код ИМХО излишен, так как это должно быть очевидно из самого кода и требует дополнительной работы при его модификации.
Другое дело — комментарий о цели кода. Очень помогает при чтении, а особенно при переделках, когда желательно быстро решить дилемму «прибить или оставить».
Согласен. Видел пример, когда ситуация была доведена до абсурда — комментариев было много, но каждый выполнял функцию к/о: описывал назначение функции ровно настолько, насколько было и так понятно из названия.

// Получаем клиента по ID
GetCustomerByID( int customerID )

Самое забавное, что в том же коде не были никак описаны действительно не очень прозрачные места.
Да, и такое бывает. Крайности :)
В приведенном примере, например, комментарии внутри метода post лишние, т.к. они ничего (кроме «to server», что скорее всего ясно из предназначения класса) не приносят. Только сложнее читать, т.к. сначала читаешь комментарий, а потом следующей строчкой код.
Да, как хорошо, что есть PEP-8 :)
А мне кажется что комментов слишком много, мешают читать.
Если методы/переменные нормально названы, не вижу в этом необходимости (если только комменты не для IDE).

Например, postCount => postCountPerSession, и можно убрать коммент. Бонус: внутри методов будет понятнее.
Комменты вроде // increment… над += 1 тоже можно убрать.
+1, пример кода на скриншоте настолько захламлён комментариями, что на него даже смотреть тошно, не то что читать.
Когда уже до всех дойдёт очевидная мысль: комментарии должны пояснять как код работает и почему именно так, а тупые комментарии с пересказом о том, что код делает никому нафиг не нужны. Во всяком случае тем, кто с используемым языком программирования знаком, понятнее будет запись на самом языке программирования, а не на английском, русском, испанском, etc. А если из самого кода программисту не понятно что он делает, то необходимо этот код выбросить вместе с комментариями.
добавлю — имена фукцний, классов и переменных должны быть на английсоком. А если вы не знаете нужного слова — потратьте минуту своего времени поглядите в словаре как же переводится на английский нужное слово.
И конечно же в идеале эти названия должны быть написаны грамматически правильно. Потому что тот кто их бегло читает — прочетет правильно а работать оно не будет.
(особенно тут вспоминается волшебное слово анализ ( analyse, analyze, analise, analysis, analisys… ну вы поняли )
О да! Присоединяюсь всеми руками и ногами.

Особено когда вижу названия вида «BaseRegistryParserShablon» или «GetSaldoBySchet» (да, это встречалось в рабочем коде).
Да, да. И опечатки, и русские буквы «с» в английских словах. Такое ощущение, что пишут без бекспейса.
UFO just landed and posted this here
Python — код, который приятно читать :)
На вкус и цвет… Мне, вот, Ruby очень нравится…
В Ruby очень много всяких @лишних: => символов. Python — он как английский язык :)
Вот маленький кусочек кода из одного проекта:
Изображение - savepic.org — сервис хранения изображений
Многим может показаться излишеством конструкция else, но мне так удобнее и понятнее.
Да, тоже приходилось часто слышать ехидные комментарии «гуру программирования» по поводу того, что тут будет все работать и без else и нечего писать лишний на код. Хотя при чтении кода сразу видна его логика и не приходится искать return выше.
Добавлю только, что лично мне приятнее else ставить на новой строчке и присваивания отделять пробелами от переменных.
многим может показаться излишним SetByte при наличии перегрузки оператора «квадратные скобки»

;-)

P.S.: а почему название метода с большой буквы, тоже привычка?
>>а почему название метода с большой буквы, тоже привычка?
Мне так удобнее хотя, наверное, следует избавляться от этой привычки.
Кстати, дефайны я пишу заглавными буквами.
А перед константами ставлю префикс k.
А почему 'k', а не 'с'? От чего образовался такой префикс?
C я юзаю для наименования класса, а k от немецкого Konstante.
Хм… мне бы и в голову не пришло. Но спасибо за развитие кругозора. И еще вопрос, Ваш пример написан на С++, я конечно понимаю что MFC это страшное наследие, и префикс 'C' в имени класса получается сам по себе, но пользуетесь ли Вы неймспейсами (namespace)?
вот кстати вспомнил про скобки. всегда их пишу даже если в условии одна строка и именно как у вас, чтобы каждая скобка на отдельной строке. тогда мозгам проще зацепиться за блок который внутри них находится, чтобы начать анализовать код. А не искать где там оно кончается.
Я тут, кстати, забыл отделить скобки условия от проверяемого выражения, т.е. сделать так:
if(_тут_пробел_IsRange(inOffset)_тут_пробел_)
а у меня даже макрос есть специальный для этого, так сказать для причёсывания кода.
Хороший пример для разбора.

1. Название функции isRange переводится как «является ли диапазоном?», что при аргументе типа unsigned int выглядит очень загадочно.

2. Обычное соглашение — возвращение признака ошибки. Если я правильно понял код, то тут при нестандартной ситуации возвращается 0, а не 1.

3. Микро-рефакторинг, соглашение, описанное у Фаулера, которое позволяет делать код проще и понятнее: сначала проверяем нестандартные ситуации, потом выполняем действия. Так мы избегаем дополнительных уровней вложенности и, что самое важное, основной код (суть функции) видно сразу: он находится в теле функции, а не в одной из веток if'ов. Это же не равноправный код — тот, которые проверяет какие-то аргументы на допустимость и тот, который выполняет собственно то, для чего функция задумана.

4. Про префиксы классов — все эти С и тд ссылка тут уже пробегала на Спольски, почитайте.

С учетом всего этого:

bool Memory::SetByte(unsigned int offset, unsigned char value)
{
    if (!inRange(offest))
        return 1
    Memory[inOffest] = value
    return 0
}
упс, С у класса-то откинул, а Memory не переименовал.

вопрос больших-маленьких букв и тд — не трогал, тут стоит просто придерживаться принятых для языка/фреймворка соглашений.
А почему не на ексепшене? И почему можно дать неправильный адрес и ничего страшного не случится? Ошибка же останется незамеченной.
Если несколько параметров и ошибка в любом вызовет один и тот же ексепшн, то не очень понятно, как это описать.
А вам не кажется, что проще передавать сразу правильные параметры, чем проверять результаты вызова каждой функции? Руки же отвалятся if'ы писать?
В том-то и дело, приходится идти на жертвы. Мы с Вами, безусловно, грамотные разработчики, которые всегда передают правильные параметры.
Но, увы, вокруг существует очень много других людей, которые могут быть не так аккуратны. А позволить своему коду оставить систему в неопределенном состоянии я не могу.
Насчет 200-300 строк в файле — далеко не всегда это возможно. Особенно, если пишется что-то чуть более сложное, чем Hello World. Я вот сейчас работаю с парой классов, у которых только декларация вдвое длиннее, а уж сам код за 3000 у каждого перевалил. Если это порезать на куски по 300 строк, из каждого файла получится десяток, и понять, как оно работает будет трудновато.
хмм… У меня вот твёрдая уверенность, что любой God Object (исключая, возможно, фасады) можно с помощью декомпозиции свести к нескольким «нормальным». Возможно, просто проблема в нежелании / нехватки времени на рефакторинг?
Не всегда это можно сделать. Вернее, сделать-то можно, только код от этого понятнее не станет. В моем примере для достижения идеала в 200-300 строк класс пришлось бы разобрать буквально на отдельные методы, а некоторые из них еще и разрезать на куски. Просто сложная обработка сложных данных.
Методы по 300 строк — это абсолютное зло. Какой бы сложности данные не были, выделить из 300 строк несколько отдельных методов можно всегда. Вопрос — насколько это хочется делать.
Вопрос, имеет ли это смысл. Представьте например, что эти 300 строк — заполнение одного объекта данными. Утрируя, это просто 300 вызовов obj.SetFoo(); obj.SetBar()… Зачем разбивать логически единый кусок на части?

Кроме того, иногда разбиение на мелкие функции сильно влияет на производительность. Например, мне надо пройтись по гигу данных (char-ов) и сконвертить их определенным образом, причем сама обработка, вобщем-то, копеечная. Можно выделить тело цикла в отдельную функцию (или даже несколько), но это будет означать тот самый гиг call-ов, так что скорость работы просядет ниже плинтуса. Оно правда нужно?
Ну так перепишите в каком-то более декларативном стиле, это ж полный трэш — 300 строк однообразных вызовов obj.SetFoo. Это не «логически единый кусок», который нельзя разбивать на части, это именно что плохой код.

А насчет производительности — думать о ней стоит тогда, когда она становится проблемой, а не заранее, оправдывая ей плохой и неструктурированный код.
Я же сказал, что это утрированно. Хорошо, другой пример: при обработке данных мне постоянно нужен десяток-другой переменных. Разбить обработку на куски — значит сделать несколько функций, которым придется передавать этот десяток переменных, причем большую часть не по значению, а по неконстантной ссылке. Вы, действительно, думаете, что это будет более читаемо? Я вам по секрету скажу, у меня есть такие функции. Там, где это действительно необходимо. Но плодить их только ради разбиения кода на мелкие куски — это безумие.

Насчет производительности: вот именно в этом месте она очень критична, поскольку объемы данных бывают очень большие (я не зря привел в примере гиг чаров, хотя в реальности все гораздо сложнее). А код вполне нормально структурирован. Просто сделано это исходя из логики работы класса, а не абстрактных ограничений на размер функции.
Думаю, мы на разных языках говорим. Альтарнатива методам на 300 строк — это никак не функции с десятками параметров. Почитайте «Рефакторинг» Фаулера, очень хорошая книга.
А какие еще альтернативы вы видите? Ну, хорошо, вспомогательный класс или структура, в которые эти переменные завернуты. На каждый существующий метод пришлось бы добавить 2-3 таких структуры. Количество кода выросло бы в 2-3 раза. Логика работы потерялась бы полностью за этими мелочами. Количество файлов выросло бы на порядок. Чтобы понять, что функция делает, пришлось бы облазить кучу кода в разных местах и понять, как он взаимодействует. И все это только для того, чтобы сократить размер функции?

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

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

Вычислительные задачи — особая область, но это не значит, что к ним не применимы современные подходы.
Тут не просто вычислительные задачи, а прмененные к биологии и биохимии. Сами биологи часто не могут внятно объяснить, чего они хотят. :)

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

Пожалуй, лишь списки констант иногда выходят очень длинными.
Да, задачи у нас несколько специфические (биоинформатика). Код часто получается сложным просто потому, что и логика обработки данных далеко не сахар.

Поддерживать 3000 строк кода одного класса в одном файле в моем случае гораздо проще, чем разбить это хозяйство на 10 классов/файлов. Я знаю о чем говорю, потому что в какой-то момент мне пришлось один класс разбить на два (по соображениям минимизации зависимостей от других библиотек). Вот теперь это настоящий кошмар — код раскидан по разным местам и уследить за ним очень трудно.
На самом, главное, чтобы код был читаемым. Все эти рекомендации, это так, для общего случая.
Вот и я о том же. :) Слепое следование строгим правилам, вроде упомянутого ниже «не более 20 строк на метод / 300 строк на класс», далеко не всегда приводит к улучшению читаемости.
С. Макконнелл «Совершенный код» тоже затрагивает поднимаемые здесь вопросы, ну и еще некоторые ;)
Пост хорош, но некоторые мысли, мне кажется, не доведены до логического завершения.
В пункте 6, к переменным с которыми предполагается сложная работа, возможно было бы полезнее сделать сеттеры и геттеры, а не описывать как правильно с ними работать.
«Совершенный код» — отличная книга. Я хотел затронуть лишь те правила, которые использую сам.
Про пункт 6 — замечание очень верное. Комментарии полей, пожалуй, больше для тех, кто будет менять класс «после нас».
Да, о «после нас» не так много кто задумывается, обычно все проходит как «ну сейчас вот так, срочно надо, а потом все исправлю и задокументирую» ;)

Готов поспорить что есть еще одно правило, которое Вы соблюдаете, но не упомянули ;)
Правило о количестве параметров передаваемых в функцию или метод.
С. Макконнелл «Совершенный код» тоже затрагивает поднимаемые здесь вопросы, ну и еще некоторые ;)
Пост хорош, но некоторые мысли, мне кажется, не доведены до логического завершения.
В пункте 6, к переменным с которыми предполагается сложная работа, возможно было бы полезнее сделать сеттеры и геттеры, а не описывать как правильно с ними работать.
Внесу свои 5 копеек. Чтобы читать было приятно не только свой код, но и весь код проекта, надо перед его началом собраться командой и написать свой CodingStyle, взяв за основу какой-либо популярный для вашего языка/платформы. При этом учесть пожелания всех, новичкам объяснить почему так писать хорошо, а так — не очень, в общем провести подготовительную работу.
Потом может пару-тройку недель инициатору придется немного контролировать процесс, указывать на ошибки, может быть вносить коррективы в документ. Но вся эта морока с лихвой окупится в дальнейшем, когда не придется разбираться в тонкостях чужой нотации и весь код буден в одном, понятном каждому стиле.
>>… и написать свой CodingStyle
После того, как возьмутся за это, до самой работы дело дойдет нескоро :) Т.к. очень уж холиварная тема для команды
UFO just landed and posted this here
А лучше по началу собираться регулярно, скажем, раз в неделю. У нашей команды одно время была практика code review, когда раз в неделю кто-то один читал код всех остальных и указывал на такие вот недостатки (плюс, естественно, архитектурные проблемы). В результате стиль кодирования был всё же выработан. и это при том, что ребята пишут на PHP.
С. Макконнелл «Совершенный код» тоже затрагивает поднимаемые здесь вопросы, ну и еще некоторые ;)
Пост хорош, но некоторые мысли, мне кажется, не доведены до логического завершения.
В пункте 6, к переменным с которыми предполагается сложная работа, возможно было бы полезнее сделать сеттеры и геттеры, а не описывать как правильно с ними работать.
Дело вкуса, конечно, но я предпочитаю укладываться в как можно меньше кода и при этом иметь как минимум 30% комментариев. Отсюда следует несколько простых правил:

1) Если возможно — не пользоваться временными переменными
2) Не ставить {} на новую строку
3) Если в методе больше 20 строк кода — то она плохо написана
4) Если в классе больше 300 строк кода — то он плохо написан
5) Если для того, чтобы получить какое-то значение из другого класса нужно соблюдать больше чем 1 уровень иерархической вложенности — то всё пропало
6) По-максимуму использовать энкапсуляцию и полиморфизм
Согласен почти со всем.

А не могли бы Вы аргументировать пункт 2 (не ставить {} на новую строку)?
исключительно потому что код тогда занимает значительно меньше места

Copy Source | Copy HTML
  1. //wtf
  2. if(foo == bar)
  3. {
  4.    if(tempVar = foobar(true))
  5.    {
  6.       print(doodle(tempVar));
  7.    }
  8.    else
  9.    {
  10.       print('No Joy');
  11.    }
  12. }
  13. else
  14. {
  15.    if(tempVar = foobar(false))
  16.    {
  17.       print(doodle(tempVar));
  18.    }
  19.    else
  20.    {
  21.       print('Really No Joy');
  22.    }
  23.  
  24. }
  25.  
  26.  
  27. //not so wtf
  28. if(foo == bar) {
  29.     if(tempVar == foobar(true)) {
  30.         print(doodle(tempVar));
  31.     } else {
  32.         print('No Joy');
  33.     }
  34. }else{
  35.     if(tempVar == foobar(false)) {
  36.         print(doodle(tempVar));
  37.     } else {
  38.         print('Really No Joy');
  39.     }
  40. }
  41.  
  42.  
  43. //totally not wtf
  44. if(foo == bar && (tempVar == fooBar(true) || tempVar == fooBar(false))) {
  45.     print(doodle(tempVar));
  46. } else {
  47.     print('No Joy');
  48. }
Намного ли хуже?

if(foo == bar && (tempVar == fooBar(true) || tempVar == fooBar(false)))
{
    print(doodle(tempVar));
}
else
{
    print('No Joy');
} 
когда кода мало — нормально, а когда много — нет
я не хочу тут начинать холивор — каждый пишет так, как ему удобнее :)
>каждый пишет так, как ему удобнее
с одной оговоркой: до тех пор, пока это не становится неудобным команде ;).

Я тоже против холиворов :)
Если в методе больше 20 строк кода — то она плохо написана

Ну это вы перегибаете, честное слово=)
От языка зависит.
я всегда годов убедиться в обратном, но пока не встречал ни одного примера!
Сомневаюсь, что вы уложитесь в 20 строк кода, когда будете писать какой-нибудь накрученный графический фильтр на C++.
Нет, вы, конечно, можете разбить весь процесс на множество маленьких функций, данные вывести в отдельные сущности, но это только ухудшит читаемость, снизит производительность и породит множество сильно связанных объектов, что противоречит шаблону «Low Coupling».
Можно взять крайний случай — ассемблер (да, бывает, пишут и на нем). Так вот там только для того, чтобы собрать в стек параметры для вызова какой-то функции, может понадобиться больше 20 строк.
Даже если не вдаваться в крайности, 20 строк — зачастую это бесполезное дробление, часто как раз ухудшающее удобочитаемость. Еще и во многих случаях влияющее на производительность.
В общем, во всякой декомпозиции должна быть мера.
Основное уже перечислили, но хочу добавить:
1) не использую тернарный условный оператор (?:) — т.к. плохо читаем
2) во всех конструкциях if (даже, если в теле только один оператор) использую фигурные коды скобки
3) стараюсь выносить числовые значения в отдельные константы, а не бросать их в коде; т.е.

Copy Source | Copy HTML
  1. // ПЛОХО
  2. if (someVariable > 10)
  3. {
  4.     // что-то там
  5. }


Copy Source | Copy HTML
  1. // ХОРОШО
  2. int tresholdValue = 10; //  пороговое значение
  3. if (someVariable > tresholdValue)
  4. {
  5.     // что-то там
  6. }
  7.  


4) Ещё, как можно увидеть из кода, люблю после символа "//" ставить пробел=)
5) А вообще советую почитать классику (Кернигана- Пайка и Макконнелла)
пункт 3 обычно приводит ещё и к более быстрому коду, так как значение переменной зачастую содержиться в регистре, а не в памяти как в неправильном варианте. по меньшей мере наблюдал это на VC++ 6.0
Это далеко не всегда. Регистров-то кот наплакал, а переменных может быть вагон и еще маленькая тележка. Даже директива register в Си, дает указание компилятору по-возможности использовать регистры для хранения переменной.
я же и написал — обычно.
особенно заметно на таких кусках (так быстрее):

int l_intSize = 374747;
for ( int l_intIndex = 0; l_intIndex < l_intSize; l_intIndex++ )


или так:
int l_intSize = l_ceSomeContainer.GetSize();
for ( int l_intIndex = 0; l_intIndex < l_intSize; l_intIndex++ )


а так вполне нормально регистров. не так давно оптимизировал распаковку одного RAW формата, так хаффман + дельта и ещё кое что, в достаточно компактном размере получились.

Если компилятор умеет оптимизировать код, то, как правило, он вынесет значение в отдельную переменную. Будет она в памяти или в регистре — этот вопрос надо изучить подробнее.

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

Вы считаете, что это плохо читается?
int max = value1 > value2
              ? value1
              : value2;

Совет — попробуйте писать в 3 строки — очень читабельно с моей точки зрения.
Лично по мне, в конструкции «if — else » сразу видно куда идёт ветвление, и какой переменной присваивается значение; в то время, как у "?:" надо напрягать мозги при определении, что означает символ "?" и ":".

Я думаю, вы согласитесь, что текстовые обозначения намного более понятны человеку, чем различные закорючки;)
Да, согласен. Но языки-то развиваются и на текстовом формате не все напишешь :)
А вообще, дело вкуса это все — кому как больше нравится.
А вообще, нашёл статью, которую стоит прочитать, прежде чем начинать делиться опытом ;):

Спасибо — очень интересная и правильная статья.

Я очень сожалею, что мой опыт показался Вам не интересным.
Ни в коем случае я Вас не имел в виду. Извините, если не так меня поняли. Я просто писал про то, что часть комментаторов здесь беззастенчиво антипаттерны используют, а часть — даже не догадываются об их существовании.
Ой, извините, я действительно не так Вас понял.

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

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

private int i = 1; // объявляем перменную i и инициализируем ее единичкой
i++; // инкрементируем переменную i

Мне они кажутся совершенно бесполезными.

Я стараюсь давать имена переменным и методам такие, чтобы код можно было читать вслух. Комментирую константы и некоторые неявные решения, если таковые имеются. Все остальные комментарии — пометки TODO.
Префиксы для полей класса _ и статических переменных __ — чтобы легчебыло читать даже без расцветки.
КОНСТАНТЫ — заглавными буквами

А вообще — читаемость кода — единственный универсальный критерий, оптимальность нужна не всюду.

Даже не только читабельность, а более общее качество — сопровождаемость. Это и читаемость и легкость модификации и легкость дебагирования
А Вы пользуетесь конструкциями вроде public static final s_defaultComparator = ...?
да, только public static final будет у меня DEFAULT_COMPARATOR
А вот private static Logger будет __logger
Ясно, спасибо. На самом деле, я больше хотел про __logger спросить :)
Меня всегда коробило писать «LOGGER.error(...)».
Бейте меня палкой, а я почти никогда не комментирую свой код :). Я стараюсь давать комментарии только в том случае, если код сильно расходится с соглашениями о кодировании на соответствующем языке.

Я не комментирую и не объясняю простые и стандартные вещи, но зато стараюсь максимально подробно комментировать сложные места и места, где, по-моему мнению, можно было сделать по-другому, но я не знаю, как :).
Если есть перечисления чего-то, или сложные условия, тогда предпочитаю писать каждое с новой строки и с учетом того что запятую или логический оператор ставлю в начало строки. Удобно отключать комментарием // (c++, java) или — (SQL) какой-то блок, при этом в целом конструкция остается синтаксически верной (за исключением комментирования первой строки):
enum{
test1
, test2
//, test3
, test4
}

if (
a==b
// && c>d
&& d!=5
){
return c-d;
}
Размер 200-300 строк имеет то недостаток что на среднем проекте у вас винчестер будет гореть красной лампочкой постоянно, загрузка проекта з 1000-2000 таких файлов даже на мощной машине удовольствие не из приятных.
Я пишу на C# и если классы связаны по смыслу пытаюсь разместить их в одном файле. Оптимум для меня 500-1000 строк, если получается больше, например при взаимодействии с native-кодом, клас делаю partial Хорошая IDE нормально можеть свернуть регионы, при нужде можно разделители поставить, монитор 24 дюйма с 16:10 в вертикальной ориентации классная штука.
А вообще жёсткая привязка в количеству строк ни к чему хорошему не приводит. Есть только один критерий связность сущностей в класе и возможность сопровождать его сложность, при превышении пороговой сложности мы пытаемся её уменьшить путём введения дополнительной сущности(нового класа). Разбиение каждый делает сам в силу своего опыта. Но этот способ не решает сложность связанную с слишком большим количеством сущностей(бритва Оккама). Множество библиотек Java, а в последнее время и .NET тяготеют к этому, получается то что я называю overcomplicated когда библиотеки стают настолько всеобъемлющие что один человек просто не может их постигнуть за приемлемые строки. Если это обосновано требованиями то пусть будет даже 1500 строчек, чем 15 с жёсткими зависимостями особенно цикличными друг к другу.

Все постигать обычно не обязательно, только базовые функции/классы и относящиеся к задаче.
Самым подозрительным в приведенном фрагменте кода является то, что метод содержит объявление только throws HabrException, а в первой же строке он бросает IllegalArgumentException. Но можно предположить, что это оговорено в соглашениях для данного проекта, поэтому не критично.

Еще одним признаком приятного кода я бы назвал расположение сначала открытых членов и только после них — закрытых. В общем случае пользователя не должна интересовать закрытая часть класса и чаще всего ищутся именно открытые члены. Более того, мне кажется естественным располагать конструктор на первом месте, перед всеми остальными методами (но после объявления открытых констант).

В вашем фрагменте конструктор не наблюдается (видимо, он определен ниже), и первое, с чем сталкивается читатель кода, это определение двух закрытых членов. Раз уж он их видел, то ему наверняка интересно будет узнать, необходимо ли их инициализировать в конструкторе. С этого момента можно считать, что данный код не является самым приятным кодом на свете, так как конструктор еще предстоит найти…
Очень интесные замечания.
IllegalArgumentException я не документирую отдельно, однако в комментарии к параметру функции указываю pre-condition («Must not be null», в случае title из примера).

Про конструктор и открые члены: абсолютно согласен. В данном примере конструктор пришлось опустить. Полностю было бы: public конструктор, public post, private sendPost.
На мой взгляд комментарии типа 'Number of posts per session' или 'Check input' даже не бесполезны, а именно вредны. Так же как и:
// Increment i
i++;

Не нужно комментировать очевидные вещи!
Как известно, финансовые и временные затраты на сопровождение программного продукта могут в несколько раз превысить затраты на его разработку. Программа, создаваемая 1 год, может использоваться 10 лет.

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


Это цитата из «Инструкции программиста», которая в свое время была «скомпилирована» мной из несольких больших статей по «правильному» программированию (уже не вспомню каких). Инструкция писалась для себя, но с прицелом на студентов-программистов, которых мне отдавали на стажировку.
Инструкция больше ориентирована на С/С++ (хотя и применима для других языков), с применением doxygen'a.

Пара выдержек:
Правила оформления исходного текста

1. Иерархия конструкций
Подчинение операторов и управляющих конструкций заключается в том, что такие операторы, как операторы цикла (for, while, do), условные операторы (if/else), операторы выбора (switch) имеют основную часть (управляющую конструкцию) и подчиненную часть.
При описании класса в качестве управляющей конструкции выступает заголовочная часть класса.
При определении функции в качестве управляющей конструкции выступает заголовок функции.

2. Количество операторов в строке
Для улучшения читаемости исходного текста программы следует располагать не более одного оператора в строке, что вызвано особенностями человеческого восприятия текста. Кроме того, это облегчает пошаговую отладку в символьных отладчиках.
Использование двух и более операторов в строке допустимо только в том случае, если это позволяет подчеркнуть некоторую систему в локальной последовательности операторов.

3. Отступы (сдвиги)
Правильное использование сдвигов или, иначе, отступов (indentation) является ключевым методом обеспечения читаемости. Идея состоит в том, что отступы зрительно показывают подчиненность (иерархию) операторов. При этом директивы препроцессора (#include, #define и т.д.), описания классов, структур, типов, глобальных данных и определения функций всегда имеют наивысший приоритет, то есть начинаются с крайней левой позиции.


Если хаброобществу интересно, готов опубликовать в виде статьи (ну и дополнить с помощью конструктивных комментариев ;-) )
У меня есть хорошее правило: если хочется написать комментарий к куску кода, то возможно, стоит подумать и попробовать сначала переписать этот кусок по-проще, ну а уж если попроще не получается, то писать комментарий, но комментировать не что код делает, а зачем он это делает.
У меня есть хорошее правило: если хочется написать комментарий к куску кода, то возможно, стоит подумать и попробовать сначала переписать этот кусок по-проще, ну а уж если попроще не получается, то писать комментарий, но комментировать не что код делает, а зачем он это делает.
Я думаю к улучшению восприятия стоит добавить соблюдения уровня абстракции внутри каждого класса, бывает читаешь код класса который отвечает за работу с персоналом, все красиво, методы называется в соответствии с этим уровнем абстракции: не addData(), а addEmployee(), и тут раз, прямой вызов запроса на MySQL и обработка результатов. Я понимаю что это называется «чтобы быстро, очень просили», но хотя бы «TODO: » комментарий можно вставит с текстом вроде «перенести в другое место, обернуть в метод»
Это очень хорошее замечание. Может быть, даже тема для поста: как сделать архитектуру такой, чтобы было просто писать читаемый код.
Хорошая мысль для статьи, спасибо.
У констант можно комменты оформить тоже как javadoc:

Не
// Number of posts per session

а
/** Number of posts per session */


Тогда они появятся в сгенерированной javadoc -документации.
Но смысл так делать, наверное, есть только в случае описания статических констант.
> только в случае описания статических констант

А как константа может быть нестатической? Приведите практический пример, если Вас не затруднит. Не могу сам себе это представить.
Извините, перемудрил с формулировкой.
Имелись ввиду константы, а не внутренние переменные класса. Т.е., public field'ы, а не private.
Ладно перемудрил, так ещё ведь и жирным выделил :-) А я сижу и в серьёз пытаюсь в голове смоделировать как это, думаю может это я уже торможу…
Очевидно, что ваш примерный код передокументирован. Там комментов больше чем самого кода. Мусорные комменты, которые просто перефразируют названия методов нужно сразу удалять. А если они всё-таки в двух словах обьясняют что-то, то лучше этими двумя словами метод и назвать. Джавадок бесспорно нужен, но остальное только засоряет.
иде отступы проставляет, только почему то у меня это происходит время от времени
> 2. Файлы не длиннее 200-300 строк У громадных файлов та же проблема, что и у некоторых швейцарских ножей: невозможно запомнить, что эта хрень делает.

Принято считать что человек может одновременно осознавать 5-9 семантических едениц. Вот у меня, кажется, это не 9 и не 7, а 3 и то с трудом (при этом IQ у меня таки выше ста, просто ёмкость внимания низкая). Сплошной кусок кода длиннее нескольких строчек из нескольких простыъ выражений меня вгоняет в ступор, а попытка в нём срочно разобраться и вовсе в панику. Настоящим спасением для меня стали «регионы» появившиеся в Visual Studio 2005. Каждый логически самостоятельный блок я закрываю в регион и сворачиваю. Потом логически связянные последовательно расположенные регионы ещё в регион вместе. В результате получается нехилое дерево регионов в каждом файле, зато всегда точно ясно что делает каждый кусочек кода в отдельности и что они делают вместе с соседями в результате.

Аналогичную систему я в своё время (когда хранимые процедуры с бизес-логикой для SQL Server для большого ERP проекта писал) приделал к SQL взяв, кажется, UltraEdit и сделав там макрос с --#region/--#endregion (на манер C#, в котором это — стандартная директива, но прикрыв директивой комментария чтобы SQL сервер не пугать). Непонятно почему Microsoft (вроде как изобретатели этого приёма) до сих пор не реализовали его своих редакторах T-SQL-кода в Visual Studio и Management Studio.
Ещё стоит, наверно, упомянуть, что в случае с большими классами иногда очень удобно делать partial классы и разносить их по нескольким файлам. Это заодно повышает удобство распределения разработки по версиям и по коллективу. Но, возвращаясь к заглавию статьи, увлекаться этим тоже не стóит, не участвовавшего в начальной разработке человека, вероятно, не меньше шокирует огромное колличество файлов и папок в исходниках.
Я мечтал написать такую статью, вот с такими же тезисами.
Все хорошее уже сделано :)
Sign up to leave a comment.

Articles